From d5d2cac60c9e8733648787ae674be1a0d1a5bd89 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 6 Jan 2021 14:42:45 -0700 Subject: [PATCH 001/136] 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 2f52da3197..5e27fe3004 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 85017cb405..c90f356517 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 bc427698ef..45075ca374 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 002/136] 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 3eb1f5cbe6..32ba6d1280 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 3566a1c4d2..1efb9052de 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 45075ca374..b846e81ecf 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 aeeefa7347..dba898693f 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 003/136] 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 488e0fc51c..15658fdb5c 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 b846e81ecf..4d98390d69 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 dba898693f..bc5e6b9920 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 004/136] 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 32ba6d1280..14751559e3 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 bc5e6b9920..3c1a864d19 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 005/136] 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 135960c124..1de63ad163 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 14751559e3..40f4d0d938 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 1efb9052de..7153eebb82 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 f7699fceda..602901f931 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 5e27fe3004..d06db22b47 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 c90f356517..890f99a3aa 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 4d98390d69..11326d82f9 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 3c1a864d19..1a25899388 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 006/136] 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 602901f931..40f92f7046 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 11326d82f9..6185c5231f 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 1a25899388..56de96be33 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 007/136] 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 40f4d0d938..e4e9802769 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 15658fdb5c..a7b23061d8 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 7153eebb82..2c5134ade1 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 40f92f7046..fe7972b493 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 d06db22b47..17e02a50cd 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 9348d67d5d..76ac139404 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 48129c5230..87f020227c 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 35ccc6e268..4a35e29390 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 6185c5231f..a5e959d9b9 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 56de96be33..df79bccea6 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 008/136] 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 e4e9802769..8f11d1d67b 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 be37873980..dc5459cab5 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 2c5134ade1..88ffe3505c 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 76ac139404..a634e7f77d 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 8a5f423a4e..93a5e33dbe 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 4a35e29390..f52c30cca1 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 a5e959d9b9..0c72c581d7 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 009/136] 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 8f11d1d67b..9d14f2b0eb 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 a7b23061d8..c80dbcbc7f 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 88ffe3505c..aa51b6afad 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 0c72c581d7..9dcb58da8c 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 df79bccea6..f16c538ac1 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 010/136] 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 1de63ad163..4d60a0ac6b 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 19f87d3631..be19be263c 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 17e02a50cd..da3f43225e 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 3729716766..f0ae80fd10 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 c2f718d3d35255552fdbe42f237a909a78a821cb Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Tue, 12 Jan 2021 14:58:24 -0300 Subject: [PATCH 011/136] Implemented Cramorant's Gulp Missile form change --- data/battle_anim_scripts.s | 17 +++++++++++ data/battle_scripts_1.s | 36 +++++++++++++++++++++++ include/battle_scripts.h | 2 ++ include/constants/battle_anim.h | 1 + include/constants/battle_config.h | 3 ++ src/battle_interface.c | 1 + src/battle_util.c | 47 +++++++++++++++++++++++++++++++ 7 files changed, 107 insertions(+) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 4bfef447b8..c3ab5b1504 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -826,6 +826,7 @@ gBattleAnims_General:: .4byte General_SlideOffScreen .4byte General_RestoreBg .4byte General_TotemFlare + .4byte General_GulpMissile .align 2 gBattleAnims_Special:: @@ -24420,6 +24421,22 @@ General_TotemFlare:: clearmonbg ANIM_ATTACKER end +General_GulpMissile: @ Modified Tackle anim (placeholder) + loadspritegfx ANIM_TAG_IMPACT + monbg ANIM_ATTACKER + setalpha 12, 8 + createsprite gHorizontalLungeSpriteTemplate, ANIM_TARGET, 2, 4, 4 + delay 6 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, ANIM_ATTACKER, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 3, 0, 6, 1 + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_ATTACKER + waitforvisualfinish + delay 10 + playse SE_EFFECTIVE + clearmonbg ANIM_ATTACKER + blendoff + end + RainbowEndureEffect: launchtemplate gBlueEndureEnergySpriteTemplate 0x2 0x4 0x0 0xffe8 0x1a 0x2 delay 0x3 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f4b2ab7a74..76eda84720 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5761,6 +5761,42 @@ BattleScript_PerishBodyActivates:: orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000 return +BattleScript_GulpMissileGorging:: + call BattleScript_AbilityPopUp + playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE, NULL + waitanimation + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000 + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER + tryfaintmon BS_ATTACKER, FALSE, NULL + handleformchange BS_TARGET, 0 + playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL + waitanimation + swapattackerwithtarget + setmoveeffect MOVE_EFFECT_PARALYSIS + seteffectprimary + swapattackerwithtarget + return + +BattleScript_GulpMissileGulping:: + call BattleScript_AbilityPopUp + playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE, NULL + waitanimation + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000 + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER + tryfaintmon BS_ATTACKER, FALSE, NULL + handleformchange BS_TARGET, 0 + playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL + waitanimation + statbuffchange STAT_BUFF_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, NULL + setgraphicalstatchangevalues + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + waitanimation + printstring STRINGID_PKMNSSTATCHANGED + waitmessage 0x40 + return + BattleScript_PerishSongCountGoesDown:: printstring STRINGID_PKMNPERISHCOUNTFELL waitmessage 0x40 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 009590f3a3..bf8700a250 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_GulpMissileGorging[]; +extern const u8 BattleScript_GulpMissileGulping[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 90766f9d59..525366df88 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -527,6 +527,7 @@ #define B_ANIM_SLIDE_OFFSCREEN 0x1E // for Emergency Exit #define B_ANIM_RESTORE_BG 0x1F // for Terrain Endings #define B_ANIM_TOTEM_FLARE 0x20 // Totem boosts aura flare +#define B_ANIM_GULP_MISSILE 0x21 // special animations table #define B_ANIM_LVL_UP 0x0 diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 6c34197ca6..69a142f23c 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -35,6 +35,9 @@ #define SPECIES_ZYGARDE 0 // 50% #define SPECIES_ZYGARDE_10 10011 // 10 % #define SPECIES_ZYGARDE_COMPLETE 10012 // 100 % + #define SPECIES_CRAMORANT 0 + #define SPECIES_CRAMORANT_GORGING 10013 + #define SPECIES_CRAMORANT_GULPING 10014 #endif // Items with peculiar battle effects. diff --git a/src/battle_interface.c b/src/battle_interface.c index 267b06ece1..0f17a79ed1 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -969,6 +969,7 @@ static void TryToggleHealboxVisibility(u8 priority, u8 healthboxLeftSpriteId, u8 case B_ANIM_TERRAIN_GRASSY: case B_ANIM_TERRAIN_ELECTRIC: case B_ANIM_TERRAIN_PSYCHIC: + case B_ANIM_GULP_MISSILE: break; } return; //all other special anims dont hide diff --git a/src/battle_util.c b/src/battle_util.c index 210f00b270..ba3874f51a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3488,6 +3488,8 @@ static bool32 ShouldChangeFormHpBased(u32 battler) {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, 2}, {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, 2}, {ABILITY_SCHOOLING, SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, 4}, + {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GORGING, 2}, + {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GULPING, 1}, }; u32 i; @@ -4689,6 +4691,39 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; + case ABILITY_GULP_MISSILE: + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && !gProtectStructs[gBattlerAttacker].confusionSelfDmg + && TARGET_TURN_DAMAGED + && IsBattlerAlive(battler) + && gBattleMons[battler].species == SPECIES_CRAMORANT_GORGING) + { + gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; + gBattleMons[battler].species = SPECIES_CRAMORANT; + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; + effect++; + } + else if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && !gProtectStructs[gBattlerAttacker].confusionSelfDmg + && TARGET_TURN_DAMAGED + && IsBattlerAlive(battler) + && gBattleMons[battler].species == SPECIES_CRAMORANT_GULPING) + { + gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; + gBattleMons[battler].species = SPECIES_CRAMORANT; + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + SET_STATCHANGER(STAT_DEF, 1, TRUE); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; + effect++; + } + break; } break; case ABILITYEFFECT_MOVE_END_ATTACKER: // Same as above, but for attacker @@ -4714,6 +4749,16 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; + case ABILITY_GULP_MISSILE: + if ((effect = ShouldChangeFormHpBased(battler)) + && (gCurrentMove == MOVE_SURF + || gStatuses3[battler] & STATUS3_UNDERWATER)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AttackerFormChange; + effect++; + } + break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -7798,6 +7843,8 @@ void UndoFormChange(u32 monId, u32 side) {SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET}, {SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW}, {SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI}, + {SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT}, + {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT}, }; currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); From 0d8f804194cbcacc9e2937f4c711b409763a6016 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 15 Jan 2021 18:11:55 -0700 Subject: [PATCH 012/136] 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 bff609d598..f256430ef1 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 009590f3a3..3b30d5bbd4 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 73b91c7087..9f02662e50 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 85017cb405..9afe5ef819 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 90e8c89671..ee97ffbba0 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 210f00b270..a0633f6cfe 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 30beb53528..aa06dea339 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 5f79efc57a..d47152f7f7 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 013/136] 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 2c179f9d5d..38cf4ea1be 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 a0633f6cfe..b095ca0fb1 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 014/136] 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 bff609d598..94dd32412e 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 f7699fceda..615af7dc5f 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 6c5f37a7d4..251f1e3356 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 210f00b270..085d63ff9c 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 015/136] 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 085d63ff9c..ebaaf386de 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 016/136] 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 b1c42e491f..ed7ecb4e06 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 94dd32412e..fd8a96f355 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 615af7dc5f..a48e037c14 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 424009d20c..01251e7936 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 251f1e3356..43acc29687 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 ebaaf386de..32264ced39 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 017/136] 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 fd8a96f355..3eb883a3d6 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 a48e037c14..c9fa1da61d 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 43acc29687..1e24b0d751 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 32264ced39..8a4428e510 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 018/136] 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 3eb883a3d6..18413b1fb8 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 a49b5d1ad0aaebeceb5a7411ce725e99153a6054 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 16 Jan 2021 16:14:36 -0700 Subject: [PATCH 019/136] prankster updated to gen 7 --- data/battle_scripts_1.s | 9 +++++++++ include/battle_scripts.h | 1 + include/constants/battle_config.h | 1 + src/battle_script_commands.c | 1 + src/battle_util.c | 18 ++++++++++++++++++ 5 files changed, 30 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bff609d598..ee5467a365 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7792,3 +7792,12 @@ BattleScript_AnnounceAirLockCloudNine:: waitmessage 0x40 call BattleScript_WeatherFormChanges end3 + +BattleScript_DarkTypePreventsPrankster:: + attackstring + ppreduce + pause 0x20 + printstring STRINGID_ITDOESNTAFFECT + waitmessage 0x40 + orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT + goto BattleScript_MoveEnd diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 009590f3a3..2434671952 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -357,5 +357,6 @@ extern const u8 BattleScript_CottonDownActivates[]; extern const u8 BattleScript_BallFetch[]; extern const u8 BattleScript_SandSpitActivates[]; extern const u8 BattleScript_PerishBodyActivates[]; +extern const u8 BattleScript_DarkTypePreventsPrankster[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index f7b38000c2..f5129a4792 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -122,6 +122,7 @@ #define B_FLASH_FIRE_FROZEN GEN_6 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. #define B_SYNCHRONIZE_NATURE GEN_6 // In Gen8+, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. #define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. +#define B_PRANKSTER GEN_7 // In Gen7, Prankster-elevated status moves do not affect Dark type Pokemon // Item settings #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. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6c5f37a7d4..b52f65e3e6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4994,6 +4994,7 @@ static void Cmd_moveend(void) MoveValuesCleanUp(); gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]); + gBattleStruct->atkCancellerTracker = 0; // run all cancellers on next target gBattlescriptCurrInstr = BattleScript_FlushMessageBox; return; } diff --git a/src/battle_util.c b/src/battle_util.c index 210f00b270..83b53ff8a5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2849,6 +2849,7 @@ enum CANCELLER_POWDER_MOVE, CANCELLER_POWDER_STATUS, CANCELLER_THROAT_CHOP, + CANCELLER_PRANKSTER, CANCELLER_END, CANCELLER_PSYCHIC_TERRAIN, CANCELLER_END2, @@ -3185,6 +3186,23 @@ u8 AtkCanceller_UnableToUseMove(void) } gBattleStruct->atkCancellerTracker++; break; + case CANCELLER_PRANKSTER: + #if B_PRANKSTER >= GEN_7 + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER + && IS_MOVE_STATUS(gCurrentMove) + && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_OPPONENTS_FIELD) + && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) + && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE)) + { + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + CancelMultiTurnMoves(gBattlerAttacker); // don't cancel moves that can hit two targets bc one target might not be protected + gBattleScripting.battler = gBattlerAbility = gBattlerTarget; + gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; + effect = 1; + } + #endif + gBattleStruct->atkCancellerTracker++; + break; case CANCELLER_END: break; } From 60f3ad77fe79e0b2bb62dc6215609b4ae9e91ab8 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 23 Jan 2021 12:40:17 -0700 Subject: [PATCH 020/136] fix prankster blocking self-targeting moves --- src/battle_util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_util.c b/src/battle_util.c index 83b53ff8a5..18a5c128c3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3190,6 +3190,7 @@ u8 AtkCanceller_UnableToUseMove(void) #if B_PRANKSTER >= GEN_7 if (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_MOVE_STATUS(gCurrentMove) + && gBattlerAttacker != gBattlerTarget && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_OPPONENTS_FIELD) && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE)) From dd51edd881ff0fa09d19f93e5aa0e66f9b374205 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 28 Jan 2021 10:51:00 -0700 Subject: [PATCH 021/136] add eerie spell, surging strikes, jungle healing --- asm/macros/battle_script.inc | 15 +++++ data/battle_anim_scripts.s | 2 +- data/battle_scripts_1.s | 68 ++++++++++++++++++- include/constants/battle_move_effects.h | 2 + include/constants/battle_script_commands.h | 3 + src/battle_script_commands.c | 76 +++++++++++++++++++++- src/data/battle_moves.h | 8 +-- src/data/pokemon/level_up_learnsets.h | 34 ---------- 8 files changed, 167 insertions(+), 41 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index b1c42e491f..208ef616c0 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1765,6 +1765,21 @@ .4byte \ptr .endm + .macro eeriespellppreduce ptr:req + various BS_TARGET, VARIOUS_EERIE_SPELL_PP_REDUCE + .4byte \ptr + .endm + + .macro jumpifteamhealthy battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_TEAM_HEALTHY + .4byte \ptr + .endm + + .macro tryhealquarterhealth battler:req, ptr:req + various \battler, VARIOUS_TRY_HEAL_QUARTER_HP + .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_anim_scripts.s b/data/battle_anim_scripts.s index c62255f892..aa97ae324d 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -14022,7 +14022,7 @@ Move_SCORCHING_SANDS:: end @to do: Move_JUNGLE_HEALING:: - end @to do: + goto Move_AROMATHERAPY Move_WICKED_BLOW:: end @to do: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bff609d598..9860fb38dc 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -365,6 +365,40 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectFairyLock .4byte BattleScript_EffectAllySwitch .4byte BattleScript_EffectSleepHit + .4byte BattleScript_EffectEerieSpell + .4byte BattleScript_EffectJungleHealing + +BattleScript_EffectJungleHealing: + attackcanceler + attackstring + ppreduce + jumpifteamhealthy BS_ATTACKER, BattleScript_ButItFailed + attackanimation + waitanimation + copybyte gBattlerTarget, gBattlerAttacker + setbyte gBattleCommunication, 0 +JungleHealing_RestoreTargetHealth: + copybyte gBattlerAttacker, gBattlerTarget + tryhealquarterhealth BS_TARGET, JungleHealing_TryCureStatus + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + printstring STRINGID_PKMNREGAINEDHEALTH + waitmessage 0x40 +JungleHealing_TryCureStatus: + jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_JungleHealingCureStatus + goto JungleHealingTryRestoreAlly +BattleScript_JungleHealingCureStatus: + curestatus BS_TARGET + updatestatusicon BS_TARGET + printstring STRINGID_PKMNSTATUSNORMAL + waitmessage 0x40 +JungleHealingTryRestoreAlly: + jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd + addbyte gBattleCommunication, 1 + jumpifnoally BS_TARGET, BattleScript_MoveEnd + setallytonexttarget JungleHealing_RestoreTargetHealth + goto BattleScript_MoveEnd BattleScript_EffectSleepHit: setmoveeffect MOVE_EFFECT_SLEEP @@ -3441,6 +3475,32 @@ BattleScript_EffectDestinyBond:: waitmessage 0x40 goto BattleScript_MoveEnd +BattleScript_EffectEerieSpell:: + attackcanceler + attackstring + ppreduce + accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + resultmessage + waitmessage 0x40 + tryfaintmon BS_TARGET, FALSE, NULL + eeriespellppreduce BattleScript_MoveEnd + printstring STRINGID_PKMNREDUCEDPP + goto BattleScript_MoveEnd + BattleScript_EffectSpite:: attackcanceler attackstring @@ -3491,7 +3551,13 @@ BattleScript_TripleKickLoop:: BattleScript_DoTripleKickAttack:: accuracycheck BattleScript_TripleKickNoMoreHits, ACC_CURR_MOVE movevaluescleanup - addbyte sTRIPLE_KICK_POWER, 10 + jumpifmove MOVE_SURGING_STRIKES, EffectTripleKick_DoDmgCalcs @ no power boost each hit + jumpifmove MOVE_TRIPLE_AXEL, EffectTripleKick_TripleAxelBoost @ triple axel gets +20 power + addbyte sTRIPLE_KICK_POWER, 10 @ triple kick gets +10 power + goto EffectTripleKick_DoDmgCalcs +EffectTripleKick_TripleAxelBoost: + addbyte sTRIPLE_KICK_POWER, 20 +EffectTripleKick_DoDmgCalcs: addbyte sMULTIHIT_STRING + 4, 0x1 critcalc damagecalc diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index b018429de4..2376336d87 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -351,5 +351,7 @@ #define EFFECT_FAIRY_LOCK 345 #define EFFECT_ALLY_SWITCH 346 #define EFFECT_SLEEP_HIT 347 // Relic Song +#define EFFECT_EERIE_SPELL 348 +#define EFFECT_JUNGLE_HEALING 349 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 424009d20c..f2e6fbf884 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -168,6 +168,9 @@ #define VARIOUS_JUMP_IF_ABSENT 101 #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 +#define VARIOUS_EERIE_SPELL_PP_REDUCE 104 +#define VARIOUS_JUMP_IF_TEAM_HEALTHY 105 +#define VARIOUS_TRY_HEAL_QUARTER_HP 106 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 66d3154a41..b053eef542 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1711,7 +1711,8 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi } else if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS || gBattleMoves[move].effect == EFFECT_ALWAYS_CRIT - || (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)) + || (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) + || move == MOVE_SURGING_STRIKES) { critChance = -2; } @@ -8333,6 +8334,79 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe) } return; + case VARIOUS_EERIE_SPELL_PP_REDUCE: + if (gLastMoves[gActiveBattler] != 0 && gLastMoves[gActiveBattler] != 0xFFFF) + { + s32 i; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gLastMoves[gActiveBattler] == gBattleMons[gActiveBattler].moves[i]) + break; + } + + if (i != MAX_MON_MOVES && gBattleMons[gActiveBattler].pp[i] != 0) + { + s32 ppToDeduct = 3; + + if (gBattleMons[gActiveBattler].pp[i] < ppToDeduct) + ppToDeduct = gBattleMons[gActiveBattler].pp[i]; + + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gActiveBattler]) + ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, STR_CONV_MODE_LEFT_ALIGN, 1); + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) + gBattleMons[gActiveBattler].pp[i] -= ppToDeduct; + if (!(gDisableStructs[gActiveBattler].mimickedMoves & gBitTable[i]) + && !(gBattleMons[gActiveBattler].status2 & STATUS2_TRANSFORMED)) + { + BtlController_EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBattler].pp[i]); + MarkBattlerForControllerExec(gActiveBattler); + } + + if (gBattleMons[gActiveBattler].pp[i] == 0) + CancelMultiTurnMoves(gActiveBattler); + + gBattlescriptCurrInstr += 7; // continue + } + else + { + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // cant reduce pp + } + } + else + { + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // cant reduce pp + } + return; + case VARIOUS_JUMP_IF_TEAM_HEALTHY: + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsBattlerAlive(BATTLE_PARTNER(gActiveBattler))) + { + u8 partner = BATTLE_PARTNER(gActiveBattler); + if ((gBattleMons[gActiveBattler].hp == gBattleMons[gActiveBattler].maxHP && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY)) + && (gBattleMons[partner].hp == gBattleMons[partner].maxHP && !(gBattleMons[partner].status1 & STATUS1_ANY))) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // fail + else + gBattlescriptCurrInstr += 7; + } + else // single battle + { + if (gBattleMons[gActiveBattler].hp == gBattleMons[gActiveBattler].maxHP && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // fail + else + gBattlescriptCurrInstr += 7; + } + return; + case VARIOUS_TRY_HEAL_QUARTER_HP: + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + + if (gBattleMons[gActiveBattler].hp == gBattleMons[gActiveBattler].maxHP) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // fail + else + gBattlescriptCurrInstr += 7; // can heal + return; } gBattlescriptCurrInstr += 3; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index fdc6b15f99..5ce967ecd0 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11306,7 +11306,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_TRIPLE_AXEL] = { - .effect = EFFECT_TRIPLE_KICK, //TODO: Increase damage by 20 instead of 10 + .effect = EFFECT_TRIPLE_KICK, .power = 20, .type = TYPE_ICE, .accuracy = 90, @@ -11348,7 +11348,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_JUNGLE_HEALING] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_JUNGLE_HEALING, .power = 0, .type = TYPE_GRASS, .accuracy = 0, @@ -11375,7 +11375,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SURGING_STRIKES] = { - .effect = EFFECT_PLACEHOLDER, //TODO (Multi hit + Always Crit) + .effect = EFFECT_TRIPLE_KICK, .power = 25, .type = TYPE_WATER, .accuracy = 100, @@ -11487,7 +11487,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_EERIE_SPELL] = { - .effect = EFFECT_HIT, // To do. It's a copy of Spite that inflicts damage and reduced the target's last move's PP by 3 instead of 4. + .effect = EFFECT_EERIE_SPELL, .power = 80, .type = TYPE_PSYCHIC, .accuracy = 100, diff --git a/src/data/pokemon/level_up_learnsets.h b/src/data/pokemon/level_up_learnsets.h index a5091c5e1c..8dd06410e2 100644 --- a/src/data/pokemon/level_up_learnsets.h +++ b/src/data/pokemon/level_up_learnsets.h @@ -1630,23 +1630,7 @@ static const struct LevelUpMove sDodrioLevelUpLearnset[] = { }; static const struct LevelUpMove sSeelLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_HEADBUTT), LEVEL_UP_MOVE( 3, MOVE_GROWL), - LEVEL_UP_MOVE( 7, MOVE_WATER_SPORT), - LEVEL_UP_MOVE(11, MOVE_ICY_WIND), - LEVEL_UP_MOVE(13, MOVE_ENCORE), - LEVEL_UP_MOVE(17, MOVE_ICE_SHARD), - LEVEL_UP_MOVE(21, MOVE_REST), - LEVEL_UP_MOVE(23, MOVE_AQUA_RING), - LEVEL_UP_MOVE(27, MOVE_AURORA_BEAM), - LEVEL_UP_MOVE(31, MOVE_AQUA_JET), - LEVEL_UP_MOVE(33, MOVE_BRINE), - LEVEL_UP_MOVE(37, MOVE_TAKE_DOWN), - LEVEL_UP_MOVE(41, MOVE_DIVE), - LEVEL_UP_MOVE(43, MOVE_AQUA_TAIL), - LEVEL_UP_MOVE(47, MOVE_ICE_BEAM), - LEVEL_UP_MOVE(51, MOVE_SAFEGUARD), - LEVEL_UP_MOVE(53, MOVE_HAIL), LEVEL_UP_END }; @@ -2355,25 +2339,7 @@ static const struct LevelUpMove sSeakingLevelUpLearnset[] = { }; static const struct LevelUpMove sStaryuLevelUpLearnset[] = { - LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE( 1, MOVE_HARDEN), - LEVEL_UP_MOVE( 4, MOVE_WATER_GUN), - LEVEL_UP_MOVE( 7, MOVE_RAPID_SPIN), - LEVEL_UP_MOVE(10, MOVE_RECOVER), - LEVEL_UP_MOVE(13, MOVE_PSYWAVE), - LEVEL_UP_MOVE(16, MOVE_SWIFT), - LEVEL_UP_MOVE(18, MOVE_BUBBLE_BEAM), - LEVEL_UP_MOVE(22, MOVE_CAMOUFLAGE), - LEVEL_UP_MOVE(24, MOVE_GYRO_BALL), - LEVEL_UP_MOVE(28, MOVE_BRINE), - LEVEL_UP_MOVE(31, MOVE_MINIMIZE), - LEVEL_UP_MOVE(35, MOVE_REFLECT_TYPE), - LEVEL_UP_MOVE(37, MOVE_POWER_GEM), - LEVEL_UP_MOVE(40, MOVE_CONFUSE_RAY), - LEVEL_UP_MOVE(42, MOVE_PSYCHIC), - LEVEL_UP_MOVE(46, MOVE_LIGHT_SCREEN), - LEVEL_UP_MOVE(49, MOVE_COSMIC_POWER), - LEVEL_UP_MOVE(53, MOVE_HYDRO_PUMP), LEVEL_UP_END }; From a37acb8345b9335e9448543379ae42a47d6fda92 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 28 Jan 2021 12:21:11 -0700 Subject: [PATCH 022/136] coaching, lash out, burning jealousy --- data/battle_anim_scripts.s | 2 +- data/battle_scripts_1.s | 31 +++++++++++++++++++++++++ include/battle.h | 2 ++ include/constants/battle.h | 3 ++- include/constants/battle_move_effects.h | 2 ++ src/battle_script_commands.c | 17 ++++++++++++-- src/battle_util.c | 4 ++++ src/data/battle_moves.h | 8 +++---- 8 files changed, 61 insertions(+), 8 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index aa97ae324d..3b3d59c828 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13995,7 +13995,7 @@ Move_SKITTER_SMACK:: end @to do: Move_BURNING_JEALOUSY:: - end @to do: + goto Move_OVERHEAT Move_LASH_OUT:: end @to do: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 9860fb38dc..39a000cbd7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -367,6 +367,36 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectSleepHit .4byte BattleScript_EffectEerieSpell .4byte BattleScript_EffectJungleHealing + .4byte BattleScript_EffectCoaching + .4byte BattleScript_EffectLashOut + +BattleScript_EffectCoaching: + attackcanceler + attackstring + ppreduce + jumpifnoally BS_ATTACKER, BattleScript_ButItFailed + copybyte gBattlerTarget, gBattlerAttacker + setallytonexttarget EffectCoaching_CheckAllyStats + goto BattleScript_ButItFailed +EffectCoaching_CheckAllyStats: + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_CoachingWorks + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 12, BattleScript_CoachingWorks + goto BattleScript_ButItFailed @ ally at max atk, def +BattleScript_CoachingWorks: + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_TARGET, BIT_ATK | BIT_DEF, 0x0 + setstatchanger STAT_ATK, 1, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_CoachingBoostDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_CoachingBoostDef + printfromtable gStatUpStringIds + waitmessage 0x40 +BattleScript_CoachingBoostDef: + setstatchanger STAT_DEF, 1, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd + printfromtable gStatUpStringIds + waitmessage 0x40 + goto BattleScript_MoveEnd BattleScript_EffectJungleHealing: attackcanceler @@ -2082,6 +2112,7 @@ BattleScript_EffectChangeTypeOnItem: BattleScript_EffectFusionCombo: BattleScript_EffectRevelationDance: BattleScript_EffectBelch: +BattleScript_EffectLashOut: BattleScript_HitFromAtkCanceler:: attackcanceler diff --git a/include/battle.h b/include/battle.h index 5917a4ab3a..632d7e7fa9 100644 --- a/include/battle.h +++ b/include/battle.h @@ -144,6 +144,8 @@ struct ProtectStruct u32 specialDmg; u8 physicalBattlerId; u8 specialBattlerId; + u8 statFell:1; // placed here since cleared at end of round + u8 statRaised:1; }; struct SpecialStatus diff --git a/include/constants/battle.h b/include/constants/battle.h index 40c604c9ed..a0c29d3cd6 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -342,7 +342,8 @@ #define MOVE_EFFECT_THROAT_CHOP 0x43 #define MOVE_EFFECT_INCINERATE 0x44 #define MOVE_EFFECT_BUG_BITE 0x45 -#define NUM_MOVE_EFFECTS 0x46 +#define MOVE_EFFECT_BURNING_JEALOUSY 0x46 +#define NUM_MOVE_EFFECTS 0x47 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 2376336d87..a15cb0c6bb 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -353,5 +353,7 @@ #define EFFECT_SLEEP_HIT 347 // Relic Song #define EFFECT_EERIE_SPELL 348 #define EFFECT_JUNGLE_HEALING 349 +#define EFFECT_COACHING 350 +#define EFFECT_LASH_OUT 351 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b053eef542..7ce9692d29 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1252,7 +1252,7 @@ static bool32 TryAegiFormChange(void) static void Cmd_attackcanceler(void) { s32 i, moveType; - + if (gBattleOutcome != 0) { gCurrentActionFuncId = B_ACTION_FINISHED; @@ -2506,6 +2506,9 @@ void SetMoveEffect(bool32 primary, u32 certain) statusChanged = TRUE; break; case STATUS1_BURN: + if (gCurrentMove == MOVE_BURNING_JEALOUSY && gProtectStructs[gEffectBattler].statRaised == 0) + break; + if (GetBattlerAbility(gEffectBattler) == ABILITY_WATER_VEIL && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) { @@ -9090,11 +9093,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; - + if (gBattleMons[gActiveBattler].statStages[statId] == MIN_STAT_STAGE) + { gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } else + { gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); + gProtectStructs[gActiveBattler].statFell = 1; + } } } else // stat increase @@ -9129,9 +9137,14 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr gBattleTextBuff2[index] = B_BUFF_EOS; if (gBattleMons[gActiveBattler].statStages[statId] == MAX_STAT_STAGE) + { gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } else + { gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); + gProtectStructs[gActiveBattler].statRaised = 1; + } } gBattleMons[gActiveBattler].statStages[statId] += statValue; diff --git a/src/battle_util.c b/src/battle_util.c index 58219080ef..69c7706b15 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6686,6 +6686,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (gBattleMoves[gLastUsedMove].effect == EFFECT_FUSION_COMBO && move != gLastUsedMove) basePower *= 2; break; + case EFFECT_LASH_OUT: + if (gProtectStructs[battlerAtk].statFell == 1) + basePower *= 2; + break; } if (basePower == 0) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 5ce967ecd0..9ba9c20bcf 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11222,12 +11222,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BURNING_JEALOUSY] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_BURN_HIT, .power = 70, .type = TYPE_FIRE, .accuracy = 100, .pp = 5, - .secondaryEffectChance = 0, + .secondaryEffectChance = 100, .target = MOVE_TARGET_BOTH, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, @@ -11236,7 +11236,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_LASH_OUT] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_LASH_OUT, .power = 75, .type = TYPE_DARK, .accuracy = 100, @@ -11278,7 +11278,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_COACHING] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_COACHING, .power = 0, .type = TYPE_FIGHTING, .accuracy = 0, From c009b51ae822b3edf0ea07f3785d4bed3c0eb43a Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 28 Jan 2021 13:27:00 -0700 Subject: [PATCH 023/136] add grassy glide, misty explosion, steel roller, obstruct, behemoth, decorate, snipe shot --- asm/macros/battle_script.inc | 4 ++ data/battle_anim_scripts.s | 4 +- data/battle_scripts_1.s | 60 ++++++++++++++++++++++ include/battle.h | 5 +- include/constants/battle.h | 2 +- include/constants/battle_move_effects.h | 5 ++ include/constants/battle_script_commands.h | 1 + src/battle_anim.c | 2 +- src/battle_bg.c | 2 +- src/battle_main.c | 7 +++ src/battle_message.c | 7 ++- src/battle_script_commands.c | 46 +++++++++++++++-- src/battle_util.c | 12 +++++ src/data/battle_moves.h | 18 +++---- 14 files changed, 155 insertions(+), 20 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 208ef616c0..371c1e27f5 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1780,6 +1780,10 @@ .4byte \ptr .endm + .macro removeterrain + various BS_ATTACKER, VARIOUS_REMOVE_TERRAIN + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 3b3d59c828..9e9f4f441f 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13492,7 +13492,7 @@ Move_BODY_PRESS:: end Move_DECORATE:: - end @to do: + goto Move_FLOWER_SHIELD Move_DRUM_BEATING:: loadspritegfx ANIM_TAG_MUSIC_NOTES @@ -13968,7 +13968,7 @@ Move_EXPANDING_FORCE:: end @to do: Move_STEEL_ROLLER:: - end @to do: + goto Move_GYRO_BALL Move_SCALE_SHOT:: end @to do: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 39a000cbd7..63f99c7a47 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -369,6 +369,62 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectJungleHealing .4byte BattleScript_EffectCoaching .4byte BattleScript_EffectLashOut + .4byte BattleScript_EffectGrassyGlide + .4byte BattleScript_EffectRemoveTerrain + .4byte BattleScript_EffectBehemoth + .4byte BattleScript_EffectDecorate + +BattleScript_EffectDecorate: + attackcanceler + attackstring + ppreduce + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, 12, BattleScript_DecorateBoost + goto BattleScript_ButItFailed +BattleScript_DecorateBoost: + attackanimation + waitanimation + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_TARGET, BIT_ATK | BIT_SPATK, 0x0 + setstatchanger STAT_ATK, 2, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_DecorateBoostSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_DecorateBoostSpAtk + printfromtable gStatUpStringIds + waitmessage 0x40 +BattleScript_DecorateBoostSpAtk: + setstatchanger STAT_SPATK, 2, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd + printfromtable gStatUpStringIds + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_EffectRemoveTerrain: + attackcanceler + attackstring + ppreduce + jumpifword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ButItFailed + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + resultmessage + waitmessage 0x40 + removeterrain + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_MoveEnd + printfromtable gTerrainEndingStringIds + waitmessage 0x40 + playanimation BS_ATTACKER, B_ANIM_RESTORE_BG, NULL + tryfaintmon BS_TARGET, FALSE, NULL + goto BattleScript_MoveEnd BattleScript_EffectCoaching: attackcanceler @@ -383,6 +439,8 @@ EffectCoaching_CheckAllyStats: jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 12, BattleScript_CoachingWorks goto BattleScript_ButItFailed @ ally at max atk, def BattleScript_CoachingWorks: + attackanimation + waitanimation setbyte sSTAT_ANIM_PLAYED, FALSE playstatchangeanimation BS_TARGET, BIT_ATK | BIT_DEF, 0x0 setstatchanger STAT_ATK, 1, FALSE @@ -2113,6 +2171,8 @@ BattleScript_EffectFusionCombo: BattleScript_EffectRevelationDance: BattleScript_EffectBelch: BattleScript_EffectLashOut: +BattleScript_EffectGrassyGlide: +BattleScript_EffectBehemoth: BattleScript_HitFromAtkCanceler:: attackcanceler diff --git a/include/battle.h b/include/battle.h index 632d7e7fa9..95f03d8e17 100644 --- a/include/battle.h +++ b/include/battle.h @@ -117,6 +117,7 @@ struct ProtectStruct u32 spikyShielded:1; u32 kingsShielded:1; u32 banefulBunkered:1; + u32 obstruct:1; u32 endured:1; u32 noValidMoves:1; u32 helpingHand:1; @@ -140,12 +141,12 @@ struct ProtectStruct u32 usedGravityPreventedMove:1; u32 powderSelfDmg:1; u32 usedThroatChopPreventedMove:1; + u32 statFell:1; + u32 statRaised:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; u8 specialBattlerId; - u8 statFell:1; // placed here since cleared at end of round - u8 statRaised:1; }; struct SpecialStatus diff --git a/include/constants/battle.h b/include/constants/battle.h index a0c29d3cd6..f9e34d88be 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -234,7 +234,7 @@ #define STATUS_FIELD_ION_DELUGE 0x400 #define STATUS_FIELD_FAIRY_LOCK 0x800 -#define STATUS_TERRAIN_ANY (STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN) +#define STATUS_FIELD_TERRAIN_ANY (STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN) // Flags describing move's result #define MOVE_RESULT_MISSED (1 << 0) diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index a15cb0c6bb..8e1f1a0cfc 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -355,5 +355,10 @@ #define EFFECT_JUNGLE_HEALING 349 #define EFFECT_COACHING 350 #define EFFECT_LASH_OUT 351 +#define EFFECT_GRASSY_GLIDE 352 +#define EFFECT_REMOVE_TERRAIN 353 +#define EFFECT_BEHEMOTH 354 +#define EFFECT_DECORATE 355 +#define EFFECT_SNIPE_SHOT 356 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index f2e6fbf884..04d8248301 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -171,6 +171,7 @@ #define VARIOUS_EERIE_SPELL_PP_REDUCE 104 #define VARIOUS_JUMP_IF_TEAM_HEALTHY 105 #define VARIOUS_TRY_HEAL_QUARTER_HP 106 +#define VARIOUS_REMOVE_TERRAIN 107 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_anim.c b/src/battle_anim.c index cb7ea5bea0..168b7a9802 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -3205,7 +3205,7 @@ static void LoadDefaultBg(void) if (IsContest()) LoadContestBgAfterMoveAnim(); #if B_TERRAIN_BG_CHANGE == TRUE - else if (gFieldStatuses & STATUS_TERRAIN_ANY) + else if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) DrawTerrainTypeBattleBackground(); #endif else diff --git a/src/battle_bg.c b/src/battle_bg.c index ca1893d652..521d0eae52 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -1422,7 +1422,7 @@ bool8 LoadChosenBattleElement(u8 caseId) void DrawTerrainTypeBattleBackground(void) { - switch (gFieldStatuses & STATUS_TERRAIN_ANY) + switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_GRASSY_TERRAIN: LoadMoveBg(BG_GRASSY_TERRAIN); diff --git a/src/battle_main.c b/src/battle_main.c index f48129acbb..0ae2ca9527 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3081,6 +3081,7 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].spikyShielded = 0; gProtectStructs[gActiveBattler].kingsShielded = 0; gProtectStructs[gActiveBattler].banefulBunkered = 0; + gProtectStructs[gActiveBattler].obstruct = 0; gProtectStructs[gActiveBattler].endured = 0; gProtectStructs[gActiveBattler].noValidMoves = 0; gProtectStructs[gActiveBattler].helpingHand = 0; @@ -3102,6 +3103,8 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].usesBouncedMove = 0; gProtectStructs[gActiveBattler].usedGravityPreventedMove = 0; gProtectStructs[gActiveBattler].usedThroatChopPreventedMove = 0; + gProtectStructs[gActiveBattler].statFell = 0; + gProtectStructs[gActiveBattler].statRaised = 0; gDisableStructs[gActiveBattler].isFirstTurn = 2; @@ -4315,6 +4318,10 @@ s8 GetMovePriority(u32 battlerId, u16 move) { priority++; } + else if (gBattleMoves[move].effect == EFFECT_GRASSY_GLIDE && gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerGrounded(battlerId)) + { + priority++; + } else if (GetBattlerAbility(battlerId) == ABILITY_TRIAGE) { switch (gBattleMoves[move].effect) diff --git a/src/battle_message.c b/src/battle_message.c index 90e8c89671..cddfb3745b 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1252,6 +1252,11 @@ const u16 gTerrainStringIds[] = STRINGID_TERRAINBECOMESMISTY, STRINGID_TERRAINBECOMESGRASSY, STRINGID_TERRAINBECOMESELECTRIC, STRINGID_TERRAINBECOMESPSYCHIC }; +const u16 gTerrainEndingStringIds[] = +{ + STRINGID_MISTYTERRAINENDS, STRINGID_GRASSYTERRAINENDS, STRINGID_ELECTRICTERRAINENDS, STRINGID_PSYCHICTERRAINENDS +}; + const u16 gTerrainPreventsStringIds[] = { STRINGID_MISTYTERRAINPREVENTS, STRINGID_ELECTRICTERRAINPREVENTS, STRINGID_PSYCHICTERRAINPREVENTS @@ -1330,7 +1335,7 @@ const u16 gRainContinuesStringIds[] = const u16 gProtectLikeUsedStringIds[] = { - STRINGID_PKMNPROTECTEDITSELF2, STRINGID_PKMNBRACEDITSELF, STRINGID_BUTITFAILED, STRINGID_PROTECTEDTEAM, + STRINGID_PKMNPROTECTEDITSELF2, STRINGID_PKMNBRACEDITSELF, STRINGID_BUTITFAILED, STRINGID_PROTECTEDTEAM }; const u16 gReflectLightScreenSafeguardStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7ce9692d29..d2bcf86b67 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1171,13 +1171,15 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) return FALSE; else if (gBattleMoves[move].effect == MOVE_EFFECT_FEINT) return FALSE; - else if (gProtectStructs[battlerId].protected) + else if (gProtectStructs[battlerId].protected && move != MOVE_DECORATE) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD && gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; else if (gProtectStructs[battlerId].banefulBunkered) return TRUE; + else if (gProtectStructs[battlerId].obstruct && !IS_MOVE_STATUS(move)) + return TRUE; else if (gProtectStructs[battlerId].spikyShielded) return TRUE; else if (gProtectStructs[battlerId].kingsShielded && gBattleMoves[move].power != 0) @@ -3126,7 +3128,8 @@ void SetMoveEffect(bool32 primary, u32 certain) || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_MAT_BLOCK || gProtectStructs[gBattlerTarget].spikyShielded || gProtectStructs[gBattlerTarget].kingsShielded - || gProtectStructs[gBattlerTarget].banefulBunkered) + || gProtectStructs[gBattlerTarget].banefulBunkered + || gProtectStructs[gBattlerTarget].obstruct) { gProtectStructs[gBattlerTarget].protected = 0; gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~(SIDE_STATUS_WIDE_GUARD); @@ -3136,6 +3139,7 @@ void SetMoveEffect(bool32 primary, u32 certain) gProtectStructs[gBattlerTarget].spikyShielded = 0; gProtectStructs[gBattlerTarget].kingsShielded = 0; gProtectStructs[gBattlerTarget].banefulBunkered = 0; + gProtectStructs[gBattlerTarget].obstruct = 0; if (gCurrentMove == MOVE_FEINT) { BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -4722,6 +4726,16 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; effect = 1; } + else if (gProtectStructs[gBattlerTarget].obstruct && gCurrentMove != MOVE_SUCKER_PUNCH) + { + i = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_2; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; + effect = 1; + } } gBattleScripting.moveendState++; break; @@ -6951,7 +6965,7 @@ static void HandleTerrainMove(u32 moveEffect) } else { - gFieldStatuses &= ~STATUS_TERRAIN_ANY; + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gFieldStatuses |= statusFlag; if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) *timer = 8; @@ -8410,6 +8424,27 @@ static void Cmd_various(void) else gBattlescriptCurrInstr += 7; // can heal return; + case VARIOUS_REMOVE_TERRAIN: + switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + { + case STATUS_FIELD_MISTY_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + break; + case STATUS_FIELD_ELECTRIC_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + break; + default: + gBattleCommunication[MULTISTRING_CHOOSER] = 4; // failsafe + break; + } + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain + break; } gBattlescriptCurrInstr += 3; @@ -8455,6 +8490,11 @@ static void Cmd_setprotectlike(void) gProtectStructs[gBattlerAttacker].banefulBunkered = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 0; } + else if (gCurrentMove == MOVE_OBSTRUCT) + { + gProtectStructs[gBattlerAttacker].obstruct = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } gDisableStructs[gBattlerAttacker].protectUses++; fail = FALSE; diff --git a/src/battle_util.c b/src/battle_util.c index 69c7706b15..326aa412c1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -141,6 +141,7 @@ void HandleAction_UseMove(void) && gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget) && gBattleMons[gSideTimers[side].followmeTarget].hp != 0 + && gBattleMoves[gCurrentMove].effect != EFFECT_SNIPE_SHOT && (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) { @@ -162,6 +163,7 @@ void HandleAction_UseMove(void) && ((GetBattlerAbility(gActiveBattler) == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) || (GetBattlerAbility(gActiveBattler) == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) && GetBattlerTurnOrderNum(gActiveBattler) < var + && gBattleMoves[gCurrentMove].effect != EFFECT_SNIPE_SHOT && (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) { @@ -6690,6 +6692,16 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (gProtectStructs[battlerAtk].statFell == 1) basePower *= 2; break; + case EFFECT_EXPLOSION: + if (move == MOVE_MISTY_EXPLOSION && gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN && IsBattlerGrounded(battlerAtk)) + basePower = 150; + break; + case EFFECT_BEHEMOTH: + #ifdef B_DYNAMAX + if (IsDynamaxed(battlerDef))/ + basePower *= 2; + #endif + break; } if (basePower == 0) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 9ba9c20bcf..5a45f8ddac 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10605,7 +10605,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SNIPE_SHOT] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_SNIPE_SHOT, .power = 80, .type = TYPE_WATER, .accuracy = 100, @@ -10613,7 +10613,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 0, .target = MOVE_TARGET_SELECTED, .priority = 0, - .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_HIGH_CRIT, .split = SPLIT_SPECIAL, }, @@ -10802,7 +10802,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_DECORATE] = { - .effect = EFFECT_PLACEHOLDER, // TODO .. EFFECT_DECORATE + .effect = EFFECT_DECORATE, .power = 0, .type = TYPE_FAIRY, .accuracy = 0, @@ -10858,7 +10858,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEHEMOTH_BLADE] = { - .effect = EFFECT_HIT, //TODO: 2x damage if dynamaxed? meh... + .effect = EFFECT_BEHEMOTH, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -10872,7 +10872,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEHEMOTH_BASH] = { - .effect = EFFECT_HIT, //TODO: 2x damage if dynamaxed? meh... + .effect = EFFECT_BEHEMOTH, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -11012,7 +11012,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_OBSTRUCT] = { - .effect = EFFECT_PLACEHOLDER, //TODO. EFFECT_PROTECT? + .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_DARK, .accuracy = 100, @@ -11096,7 +11096,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_STEEL_ROLLER] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_REMOVE_TERRAIN, .power = 130, .type = TYPE_STEEL, .accuracy = 100, @@ -11152,7 +11152,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_MISTY_EXPLOSION] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_EXPLOSION, .power = 100, .type = TYPE_FAIRY, .accuracy = 100, @@ -11166,7 +11166,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_GRASSY_GLIDE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_GRASSY_GLIDE, .power = 70, .type = TYPE_GRASS, .accuracy = 100, From e11100b030f51f6c2b64888c79683c22b24ad8d2 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 28 Jan 2021 13:31:57 -0700 Subject: [PATCH 024/136] fix temp learnsets --- src/data/pokemon/level_up_learnsets.h | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/data/pokemon/level_up_learnsets.h b/src/data/pokemon/level_up_learnsets.h index 8dd06410e2..a5091c5e1c 100644 --- a/src/data/pokemon/level_up_learnsets.h +++ b/src/data/pokemon/level_up_learnsets.h @@ -1630,7 +1630,23 @@ static const struct LevelUpMove sDodrioLevelUpLearnset[] = { }; static const struct LevelUpMove sSeelLevelUpLearnset[] = { + LEVEL_UP_MOVE( 1, MOVE_HEADBUTT), LEVEL_UP_MOVE( 3, MOVE_GROWL), + LEVEL_UP_MOVE( 7, MOVE_WATER_SPORT), + LEVEL_UP_MOVE(11, MOVE_ICY_WIND), + LEVEL_UP_MOVE(13, MOVE_ENCORE), + LEVEL_UP_MOVE(17, MOVE_ICE_SHARD), + LEVEL_UP_MOVE(21, MOVE_REST), + LEVEL_UP_MOVE(23, MOVE_AQUA_RING), + LEVEL_UP_MOVE(27, MOVE_AURORA_BEAM), + LEVEL_UP_MOVE(31, MOVE_AQUA_JET), + LEVEL_UP_MOVE(33, MOVE_BRINE), + LEVEL_UP_MOVE(37, MOVE_TAKE_DOWN), + LEVEL_UP_MOVE(41, MOVE_DIVE), + LEVEL_UP_MOVE(43, MOVE_AQUA_TAIL), + LEVEL_UP_MOVE(47, MOVE_ICE_BEAM), + LEVEL_UP_MOVE(51, MOVE_SAFEGUARD), + LEVEL_UP_MOVE(53, MOVE_HAIL), LEVEL_UP_END }; @@ -2339,7 +2355,25 @@ static const struct LevelUpMove sSeakingLevelUpLearnset[] = { }; static const struct LevelUpMove sStaryuLevelUpLearnset[] = { + LEVEL_UP_MOVE( 1, MOVE_TACKLE), LEVEL_UP_MOVE( 1, MOVE_HARDEN), + LEVEL_UP_MOVE( 4, MOVE_WATER_GUN), + LEVEL_UP_MOVE( 7, MOVE_RAPID_SPIN), + LEVEL_UP_MOVE(10, MOVE_RECOVER), + LEVEL_UP_MOVE(13, MOVE_PSYWAVE), + LEVEL_UP_MOVE(16, MOVE_SWIFT), + LEVEL_UP_MOVE(18, MOVE_BUBBLE_BEAM), + LEVEL_UP_MOVE(22, MOVE_CAMOUFLAGE), + LEVEL_UP_MOVE(24, MOVE_GYRO_BALL), + LEVEL_UP_MOVE(28, MOVE_BRINE), + LEVEL_UP_MOVE(31, MOVE_MINIMIZE), + LEVEL_UP_MOVE(35, MOVE_REFLECT_TYPE), + LEVEL_UP_MOVE(37, MOVE_POWER_GEM), + LEVEL_UP_MOVE(40, MOVE_CONFUSE_RAY), + LEVEL_UP_MOVE(42, MOVE_PSYCHIC), + LEVEL_UP_MOVE(46, MOVE_LIGHT_SCREEN), + LEVEL_UP_MOVE(49, MOVE_COSMIC_POWER), + LEVEL_UP_MOVE(53, MOVE_HYDRO_PUMP), LEVEL_UP_END }; From 9fcf7d2453bcb199a1987dc3cb3099c621bd03ab Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 28 Jan 2021 13:51:39 -0700 Subject: [PATCH 025/136] zero terrain timers for steel roll, remove unused move effectd --- include/constants/battle.h | 3 +-- src/battle_script_commands.c | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index f9e34d88be..48616d6cd1 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -342,8 +342,7 @@ #define MOVE_EFFECT_THROAT_CHOP 0x43 #define MOVE_EFFECT_INCINERATE 0x44 #define MOVE_EFFECT_BUG_BITE 0x45 -#define MOVE_EFFECT_BURNING_JEALOUSY 0x46 -#define NUM_MOVE_EFFECTS 0x47 +#define NUM_MOVE_EFFECTS 0x46 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d2bcf86b67..bdefc61c66 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8428,15 +8428,19 @@ static void Cmd_various(void) switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_MISTY_TERRAIN: + gFieldTimers.mistyTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 0; break; case STATUS_FIELD_GRASSY_TERRAIN: + gFieldTimers.grassyTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 1; break; case STATUS_FIELD_ELECTRIC_TERRAIN: + gFieldTimers.electricTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 2; break; case STATUS_FIELD_PSYCHIC_TERRAIN: + gFieldTimers.psychicTerrainTimer = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 3; break; default: From d5004638a933ed9394be4b2409ef8b7aa8c701e6 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Tue, 9 Mar 2021 16:35:47 -0700 Subject: [PATCH 026/136] Update include/constants/battle_config.h Co-authored-by: Eduardo Quezada D'Ottone --- include/constants/battle_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index f5129a4792..125088d78f 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -122,7 +122,7 @@ #define B_FLASH_FIRE_FROZEN GEN_6 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. #define B_SYNCHRONIZE_NATURE GEN_6 // In Gen8+, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. #define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. -#define B_PRANKSTER GEN_7 // In Gen7, Prankster-elevated status moves do not affect Dark type Pokemon +#define B_PRANKSTER_DARK_TYPES GEN_7 // In Gen7, Prankster-elevated status moves do not affect Dark type Pokémon. // Item settings #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. From 208b964a5682789b3bb9df04faf12ba47ebc7319 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Tue, 9 Mar 2021 16:35:56 -0700 Subject: [PATCH 027/136] Update src/battle_util.c Co-authored-by: Eduardo Quezada D'Ottone --- 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 18a5c128c3..e5d13283b4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3187,7 +3187,7 @@ u8 AtkCanceller_UnableToUseMove(void) gBattleStruct->atkCancellerTracker++; break; case CANCELLER_PRANKSTER: - #if B_PRANKSTER >= GEN_7 + #if B_PRANKSTER_DARK_TYPES >= GEN_7 if (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_MOVE_STATUS(gCurrentMove) && gBattlerAttacker != gBattlerTarget 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 028/136] 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 b095ca0fb1..f62228c46a 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 029/136] 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 f62228c46a..bc3418a916 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 030/136] 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 bc3418a916..aecdb445da 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 031/136] 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 aecdb445da..da9cae886b 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 032/136] 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 da9cae886b..e71db412e6 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 033/136] 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 e71db412e6..f56a37a360 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 034/136] 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 f56a37a360..f44146f11a 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 035/136] 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 f44146f11a..661f7068ef 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 4b29ae39ad6830f8aa0e31d1182a991b338bd722 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 8 Jun 2021 16:40:47 +0200 Subject: [PATCH 036/136] Allow one mon double battles --- include/battle_controllers.h | 1 + src/battle_controller_player.c | 49 +++++++++++++++++++--------------- src/battle_controllers.c | 36 ++++++++++++------------- src/battle_main.c | 15 ++++++++--- src/battle_message.c | 2 +- 5 files changed, 58 insertions(+), 45 deletions(-) diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 1cedf81fa4..71ca640976 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -185,6 +185,7 @@ extern struct UnusedControllerStruct gUnusedControllerStruct; void HandleLinkBattleSetup(void); void SetUpBattleVarsAndBirchZigzagoon(void); void InitBattleControllers(void); +bool32 IsValidForBattle(struct Pokemon *mon); void TryReceiveLinkBattleData(void); void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 89f73ffc41..59827ca80b 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1034,20 +1034,25 @@ static void Intro_DelayAndEnd(void) } } +static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active. +{ + return (IsDoubleBattle() && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[battlerId ^ BIT_FLANK]])); +} + static void Intro_WaitForShinyAnimAndHealthbox(void) { bool8 healthboxAnimDone = FALSE; // Check if healthbox has finished sliding in - if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { - if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; } else { - if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy - && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy) + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; } @@ -1065,7 +1070,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(void) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); - if (IsDoubleBattle()) + if (TwoIntroMons(gActiveBattler)) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], gActiveBattler ^ BIT_FLANK); gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].introEndDelay = 3; @@ -1094,7 +1099,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].healthboxSlideInStarted) { - if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], HEALTHBOX_ALL); StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK); @@ -1125,15 +1130,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) } // Wait for battler anims - if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) - { - if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy - && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) - { - battlerAnimsDone = TRUE; - } - } - else + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy @@ -1143,11 +1140,19 @@ static void Intro_TryShinyAnimShowHealthbox(void) battlerAnimsDone = TRUE; } } + else + { + if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + { + battlerAnimsDone = TRUE; + } + } // Clean up if (bgmRestored && battlerAnimsDone) { - if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) DestroySprite(&gSprites[gBattleControllerData[gActiveBattler ^ BIT_FLANK]]); DestroySprite(&gSprites[gBattleControllerData[gActiveBattler]]); @@ -3114,12 +3119,7 @@ static void Task_StartSendOutAnim(u8 taskId) u8 savedActiveBattler = gActiveBattler; gActiveBattler = gTasks[taskId].tBattlerId; - if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) - { - gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; - StartSendOutAnim(gActiveBattler, FALSE); - } - else + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); @@ -3129,6 +3129,11 @@ static void Task_StartSendOutAnim(u8 taskId) StartSendOutAnim(gActiveBattler, FALSE); gActiveBattler ^= BIT_FLANK; } + else + { + gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + StartSendOutAnim(gActiveBattler, FALSE); + } gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; gActiveBattler = savedActiveBattler; DestroyTask(taskId); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 2fc7cac075..033a121228 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -588,6 +588,14 @@ static void InitLinkBtlControllers(void) } } +bool32 IsValidForBattle(struct Pokemon *mon) +{ + u32 species = GetMonData(mon, MON_DATA_SPECIES2); + return (species != SPECIES_NONE && species != SPECIES_EGG + && GetMonData(mon, MON_DATA_HP) != 0 + && GetMonData(mon, MON_DATA_IS_EGG) == 0); +} + static void SetBattlePartyIds(void) { s32 i, j; @@ -602,10 +610,7 @@ static void SetBattlePartyIds(void) { if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) { - if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0) + if (IsValidForBattle(&gPlayerParty[j])) { gBattlerPartyIndexes[i] = j; break; @@ -613,10 +618,7 @@ static void SetBattlePartyIds(void) } else { - if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0) + if (IsValidForBattle(&gEnemyParty[j])) { gBattlerPartyIndexes[i] = j; break; @@ -627,11 +629,7 @@ static void SetBattlePartyIds(void) { if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) { - if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES) != SPECIES_NONE // Probably a typo by Game Freak. The rest use SPECIES2. - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0 - && gBattlerPartyIndexes[i - 2] != j) + if (IsValidForBattle(&gPlayerParty[j]) && gBattlerPartyIndexes[i - 2] != j) { gBattlerPartyIndexes[i] = j; break; @@ -639,16 +637,18 @@ static void SetBattlePartyIds(void) } else { - if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0 - && gBattlerPartyIndexes[i - 2] != j) + if (IsValidForBattle(&gEnemyParty[j]) && gBattlerPartyIndexes[i - 2] != j) { gBattlerPartyIndexes[i] = j; break; } } + + // No valid mons were found. Add the empty slot. + if (gBattlerPartyIndexes[i - 2] == 0) + gBattlerPartyIndexes[i] = 1; + else + gBattlerPartyIndexes[i] = 0; } } } diff --git a/src/battle_main.c b/src/battle_main.c index 9cf56abf74..f6d1cbe62a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3454,6 +3454,13 @@ static void TryDoEventsBeforeFirstTurn(void) if (gBattleControllerExecFlags) return; + // Set invalid mons as absent(for example when starting a double battle with only one pokemon). + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE) + gAbsentBattlerFlags |= gBitTable[i]; + } + if (gBattleStruct->switchInAbilitiesCounter == 0) { for (i = 0; i < gBattlersCount; i++) @@ -4080,10 +4087,10 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED_STANDBY: - if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) + if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF << 28) - | (gBitTable[gActiveBattler] << 4) - | (gBitTable[gActiveBattler] << 8) + | (gBitTable[gActiveBattler] << 4) + | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 12)))) { if (AllAtActionConfirmed()) @@ -4646,7 +4653,7 @@ static void CheckQuickClaw_CustapBerryActivation(void) } } } - + // setup stuff before turns/actions TryClearRageAndFuryCutter(); gCurrentTurnActionNumber = 0; diff --git a/src/battle_message.c b/src/battle_message.c index c4f043e150..8ef2e4702f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2560,7 +2560,7 @@ void BufferStringBattle(u16 stringID) case STRINGID_INTROSENDOUT: // poke first send-out if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) stringPtr = sText_InGamePartnerSentOutZGoN; From 540719c48323dd5fe56f585ba5b613f769a78276 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 8 Jun 2021 22:50:37 +0200 Subject: [PATCH 037/136] Add support for only one enemy pokemon in double battles start --- src/battle_controller_opponent.c | 22 +++++++++++++++------- src/battle_message.c | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 4eeef55c3d..928fc310f8 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -225,12 +225,18 @@ static void Intro_DelayAndEnd(void) } } +static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active. +{ + return (IsDoubleBattle() && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[battlerId ^ BIT_FLANK]])); +} + static void Intro_WaitForShinyAnimAndHealthbox(void) { bool8 healthboxAnimDone = FALSE; bool8 twoMons; - if (!IsDoubleBattle() || ((IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI) && !BATTLE_TWO_VS_ONE_OPPONENT) || (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) + twoMons = TwoIntroMons(gActiveBattler); + if (!twoMons || ((twoMons && (gBattleTypeFlags & BATTLE_TYPE_MULTI) && !BATTLE_TWO_VS_ONE_OPPONENT) || (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) { if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; @@ -292,15 +298,17 @@ static void Intro_TryShinyAnimShowHealthbox(void) { bool32 bgmRestored = FALSE; bool32 battlerAnimsDone = FALSE; + bool32 twoMons; if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].finishedShinyMonAnim) TryShinyAnimation(gActiveBattler, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]); + twoMons = TwoIntroMons(gActiveBattler); if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT) - && IsDoubleBattle() + && twoMons && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].finishedShinyMonAnim) @@ -310,7 +318,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].healthboxSlideInStarted) { - if (IsDoubleBattle() && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) + if (twoMons && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) { UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], HEALTHBOX_ALL); StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK); @@ -342,7 +350,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) bgmRestored = TRUE; } - if (!IsDoubleBattle() || (IsDoubleBattle() && gBattleTypeFlags & BATTLE_TYPE_MULTI && !BATTLE_TWO_VS_ONE_OPPONENT)) + if (!twoMons || (twoMons && gBattleTypeFlags & BATTLE_TYPE_MULTI && !BATTLE_TWO_VS_ONE_OPPONENT)) { if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) @@ -363,7 +371,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) if (bgmRestored && battlerAnimsDone) { - if (IsDoubleBattle() && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) + if (twoMons && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) { DestroySprite(&gSprites[gBattleControllerData[gActiveBattler ^ BIT_FLANK]]); SetBattlerShadowSpriteCallback(gActiveBattler ^ BIT_FLANK, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], MON_DATA_SPECIES)); @@ -469,7 +477,7 @@ static void SwitchIn_HandleSoundAndEnd(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive && !IsCryPlayingOrClearCrySongs()) { - if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy || gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy_2) { m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100); @@ -1892,7 +1900,7 @@ static void Task_StartSendOutAnim(u8 taskId) u8 savedActiveBank = gActiveBattler; gActiveBattler = gTasks[taskId].data[0]; - if ((!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) && !BATTLE_TWO_VS_ONE_OPPONENT) + if ((!TwoIntroMons(gActiveBattler) || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) && !BATTLE_TWO_VS_ONE_OPPONENT) { gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); diff --git a/src/battle_message.c b/src/battle_message.c index 8ef2e4702f..e77a5e0b46 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2549,7 +2549,7 @@ void BufferStringBattle(u16 stringID) { if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) stringPtr = sText_LegendaryPkmnAppeared; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) // interesting, looks like they had something planned for wild double battles + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) // interesting, looks like they had something planned for wild double battles stringPtr = sText_TwoWildPkmnAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) stringPtr = sText_WildPkmnAppearedPause; @@ -2578,7 +2578,7 @@ void BufferStringBattle(u16 stringID) } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) { if (BATTLE_TWO_VS_ONE_OPPONENT) stringPtr = sText_Trainer1SentOutTwoPkmn; From 2d41f08312e2b1e39b5c964ab2a644a3ee1392ec Mon Sep 17 00:00:00 2001 From: StubbornOne Date: Mon, 21 Jun 2021 14:18:33 +0800 Subject: [PATCH 038/136] Add Telepathy's damage prevention effect --- src/battle_util.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 87f9003e0b..06ccae3b69 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8105,6 +8105,17 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat RecordAbilityBattle(battlerDef, ABILITY_WONDER_GUARD); } } + if (GetBattlerAbility(battlerDef) == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk)) { + modifier = UQ_4_12(0.0); + if (recordAbilities) + { + gLastUsedAbility = ABILITY_TELEPATHY; + gMoveResultFlags |= MOVE_RESULT_MISSED; + gLastLandedMoves[battlerDef] = 0; + gBattleCommunication[6] = B_MSG_AVOIDED_DMG; + RecordAbilityBattle(battlerDef, ABILITY_TELEPATHY); + } + } return modifier; } From c914ed8572c800d9239642ee2f92cc6124d1dbda Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 25 Jul 2021 09:38:54 -0600 Subject: [PATCH 039/136] fix sucker punch, surging strikes, obstruct, and snipe shot --- asm/macros/battle_script.inc | 5 +++ data/battle_scripts_1.s | 39 +++++++++++++++++---- include/battle.h | 2 +- include/constants/battle_move_effects.h | 5 +-- include/constants/battle_script_commands.h | 1 + src/battle_main.c | 2 +- src/battle_script_commands.c | 40 ++++++++++++++++------ src/battle_util.c | 6 ++-- src/data/battle_moves.h | 8 ++--- 9 files changed, 80 insertions(+), 28 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9d2c58b56b..6aacc37de9 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1787,6 +1787,11 @@ .macro removeterrain various BS_ATTACKER, VARIOUS_REMOVE_TERRAIN .endm + + .macro jumpifobstruct ptr:req + various BS_ATTACKER, VARIOUS_JUMP_IF_OBSTRUCT + .4byte \ptr + .endm @ helpful macros .macro setstatchanger stat:req, stages:req, down:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a376ae4ef6..8ff056d762 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -374,8 +374,10 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectLashOut .4byte BattleScript_EffectGrassyGlide .4byte BattleScript_EffectRemoveTerrain - .4byte BattleScript_EffectBehemoth + .4byte BattleScript_EffectDynamaxDoubleDmg .4byte BattleScript_EffectDecorate + .4byte BattleScript_EffectSnipeShot + .4byte BattleScript_EffectTripleHit BattleScript_EffectDecorate: attackcanceler @@ -470,22 +472,22 @@ BattleScript_EffectJungleHealing: setbyte gBattleCommunication, 0 JungleHealing_RestoreTargetHealth: copybyte gBattlerAttacker, gBattlerTarget - tryhealquarterhealth BS_TARGET, JungleHealing_TryCureStatus + tryhealquarterhealth BS_TARGET, BattleScript_JungleHealing_TryCureStatus orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE healthbarupdate BS_TARGET datahpupdate BS_TARGET printstring STRINGID_PKMNREGAINEDHEALTH waitmessage 0x40 -JungleHealing_TryCureStatus: - jumpifmove MOVE_LIFE_DEW, JungleHealingTryRestoreAlly @ life dew only heals +BattleScript_JungleHealing_TryCureStatus: + jumpifmove MOVE_LIFE_DEW, BattleScript_JungleHealingTryRestoreAlly @ life dew only heals jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_JungleHealingCureStatus - goto JungleHealingTryRestoreAlly + goto BattleScript_JungleHealingTryRestoreAlly BattleScript_JungleHealingCureStatus: curestatus BS_TARGET updatestatusicon BS_TARGET printstring STRINGID_PKMNSTATUSNORMAL waitmessage 0x40 -JungleHealingTryRestoreAlly: +BattleScript_JungleHealingTryRestoreAlly: jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd addbyte gBattleCommunication, 1 jumpifnoally BS_TARGET, BattleScript_MoveEnd @@ -2183,7 +2185,8 @@ BattleScript_EffectBelch: BattleScript_EffectBodyPress: BattleScript_EffectLashOut: BattleScript_EffectGrassyGlide: -BattleScript_EffectBehemoth: +BattleScript_EffectDynamaxDoubleDmg: +BattleScript_EffectSnipeShot: BattleScript_HitFromAtkCanceler:: attackcanceler @@ -2255,6 +2258,17 @@ BattleScript_MoveMissed:: effectivenesssound resultmessage waitmessage B_WAIT_TIME_LONG + jumpifobstruct BattleScript_ObstructActivates + goto BattleScript_MoveEnd + +BattleScript_ObstructActivates: + jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_DEF, MIN_STAT_STAGE, BattleScript_ObstructActivationEnd + setgraphicalstatchangevalues + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_ObstructActivationEnd + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_ObstructActivationEnd: goto BattleScript_MoveEnd BattleScript_EffectSleep:: @@ -2932,6 +2946,16 @@ BattleScript_EffectTrap:: setmoveeffect MOVE_EFFECT_WRAP goto BattleScript_EffectHit +BattleScript_EffectTripleHit:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + setmultihitcounter 3 + initmultihitstring + sethword sMULTIHIT_EFFECT, 0 + goto BattleScript_MultiHitLoop + BattleScript_EffectDoubleHit:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE @@ -8130,3 +8154,4 @@ BattleScript_JabocaRowapBerryActivate_Dmg: call BattleScript_HurtAttacker removeitem BS_TARGET return + diff --git a/include/battle.h b/include/battle.h index 3dfe8f42ab..73de6fadfe 100644 --- a/include/battle.h +++ b/include/battle.h @@ -119,7 +119,7 @@ struct ProtectStruct u32 spikyShielded:1; u32 kingsShielded:1; u32 banefulBunkered:1; - u32 obstruct:1; + u32 obstructed:1; u32 endured:1; u32 noValidMoves:1; u32 helpingHand:1; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 7690c974f0..43b5615a57 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -358,10 +358,11 @@ #define EFFECT_LASH_OUT 352 #define EFFECT_GRASSY_GLIDE 353 #define EFFECT_REMOVE_TERRAIN 354 -#define EFFECT_BEHEMOTH 355 +#define EFFECT_DYNAMAX_DOUBLE_DMG 355 #define EFFECT_DECORATE 356 #define EFFECT_SNIPE_SHOT 357 +#define EFFECT_TRIPLE_HIT 358 -#define NUM_BATTLE_MOVE_EFFECTS 358 +#define NUM_BATTLE_MOVE_EFFECTS 359 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index d0d5a7899e..c23ec6c635 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -177,6 +177,7 @@ #define VARIOUS_JUMP_IF_TEAM_HEALTHY 106 #define VARIOUS_TRY_HEAL_QUARTER_HP 107 #define VARIOUS_REMOVE_TERRAIN 108 +#define VARIOUS_JUMP_IF_OBSTRUCT 109 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_main.c b/src/battle_main.c index 844d0e20ef..1dada5a2eb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3064,7 +3064,7 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].spikyShielded = 0; gProtectStructs[gActiveBattler].kingsShielded = 0; gProtectStructs[gActiveBattler].banefulBunkered = 0; - gProtectStructs[gActiveBattler].obstruct = 0; + gProtectStructs[gActiveBattler].obstructed = 0; gProtectStructs[gActiveBattler].endured = 0; gProtectStructs[gActiveBattler].noValidMoves = 0; gProtectStructs[gActiveBattler].helpingHand = 0; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f4a1c879f7..5b2c9e4a46 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1241,14 +1241,18 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) return FALSE; else if (gBattleMoves[move].effect == MOVE_EFFECT_FEINT) return FALSE; - else if (gProtectStructs[battlerId].protected && move != MOVE_DECORATE) + else if (gProtectStructs[battlerId].protected) + { + if (move == MOVE_DECORATE && !(gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD)) + return FALSE; // decorate bypasses protect and detect, but not crafty shield return TRUE; + } else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD && gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; else if (gProtectStructs[battlerId].banefulBunkered) return TRUE; - else if (gProtectStructs[battlerId].obstruct && !IS_MOVE_STATUS(move)) + else if (gProtectStructs[battlerId].obstructed && !IS_MOVE_STATUS(move)) return TRUE; else if (gProtectStructs[battlerId].spikyShielded) return TRUE; @@ -1258,10 +1262,10 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) && GetChosenMovePriority(gBattlerAttacker) > 0) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD - && gBattleMoves[move].power == 0) + && IS_MOVE_STATUS(move)) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK - && gBattleMoves[move].power != 0) + && !IS_MOVE_STATUS(move)) return TRUE; else return FALSE; @@ -1324,7 +1328,7 @@ static bool32 TryAegiFormChange(void) static void Cmd_attackcanceler(void) { s32 i, moveType; - + if (gBattleOutcome != 0) { gCurrentActionFuncId = B_ACTION_FINISHED; @@ -3203,7 +3207,7 @@ void SetMoveEffect(bool32 primary, u32 certain) || gProtectStructs[gBattlerTarget].spikyShielded || gProtectStructs[gBattlerTarget].kingsShielded || gProtectStructs[gBattlerTarget].banefulBunkered - || gProtectStructs[gBattlerTarget].obstruct) + || gProtectStructs[gBattlerTarget].obstructed) { gProtectStructs[gBattlerTarget].protected = 0; gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~(SIDE_STATUS_WIDE_GUARD); @@ -3213,7 +3217,7 @@ void SetMoveEffect(bool32 primary, u32 certain) gProtectStructs[gBattlerTarget].spikyShielded = 0; gProtectStructs[gBattlerTarget].kingsShielded = 0; gProtectStructs[gBattlerTarget].banefulBunkered = 0; - gProtectStructs[gBattlerTarget].obstruct = 0; + gProtectStructs[gBattlerTarget].obstructed = 0; if (gCurrentMove == MOVE_FEINT) { BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -4814,7 +4818,7 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; effect = 1; } - else if (gProtectStructs[gBattlerTarget].obstruct && gCurrentMove != MOVE_SUCKER_PUNCH) + else if (gProtectStructs[gBattlerTarget].obstructed && gCurrentMove != MOVE_SUCKER_PUNCH) { i = gBattlerAttacker; gBattlerAttacker = gBattlerTarget; @@ -7766,7 +7770,9 @@ static void Cmd_various(void) } return; case VARIOUS_SUCKER_PUNCH_CHECK: - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + if (gProtectStructs[gBattlerTarget].obstructed) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else if (gBattleMoves[gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]].power == 0) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); @@ -8538,6 +8544,20 @@ static void Cmd_various(void) } gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain break; + case VARIOUS_JUMP_IF_OBSTRUCT: + // if obstruct blocked a contact move, sharply lower defense + if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker) && gProtectStructs[gBattlerTarget].obstructed && !IS_MOVE_STATUS(gCurrentMove)) + { + SET_STATCHANGER(STAT_DEF, 2, TRUE); + gBattleScripting.battler = gBattlerAttacker; + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + } + else + { + gBattlescriptCurrInstr += 7; + + } + return; } gBattlescriptCurrInstr += 3; @@ -8585,7 +8605,7 @@ static void Cmd_setprotectlike(void) } else if (gCurrentMove == MOVE_OBSTRUCT) { - gProtectStructs[gBattlerAttacker].obstruct = 1; + gProtectStructs[gBattlerAttacker].obstructed = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 0; } diff --git a/src/battle_util.c b/src/battle_util.c index babd0b5d41..5a415ce66b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7199,11 +7199,11 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_EXPLOSION: if (move == MOVE_MISTY_EXPLOSION && gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN && IsBattlerGrounded(battlerAtk)) - basePower = 150; + MulModifier(&basePower, UQ_4_12(1.5)); break; - case EFFECT_BEHEMOTH: + case EFFECT_DYNAMAX_DOUBLE_DMG: #ifdef B_DYNAMAX - if (IsDynamaxed(battlerDef))/ + if (IsDynamaxed(battlerDef)) basePower *= 2; #endif break; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 5c4a035a50..be4240a21b 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10996,7 +10996,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEHEMOTH_BLADE] = { - .effect = EFFECT_BEHEMOTH, + .effect = EFFECT_DYNAMAX_DOUBLE_DMG, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -11010,7 +11010,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEHEMOTH_BASH] = { - .effect = EFFECT_BEHEMOTH, + .effect = EFFECT_DYNAMAX_DOUBLE_DMG, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -11158,7 +11158,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 0, .target = MOVE_TARGET_USER, .priority = 4, - .flags = 0, + .flags = FLAG_PROTECTION_MOVE, .split = SPLIT_STATUS, }, @@ -11513,7 +11513,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SURGING_STRIKES] = { - .effect = EFFECT_TRIPLE_KICK, + .effect = EFFECT_TRIPLE_HIT, .power = 25, .type = TYPE_WATER, .accuracy = 100, From 1f3983cb05fc91945004c5dd75507def95e01c05 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 7 Aug 2021 20:38:35 +1200 Subject: [PATCH 040/136] Shields Down protects all meteor form Minior This was only working with red core minior. --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index de7105a270..104c528b82 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7138,7 +7138,7 @@ u32 IsLeafGuardProtected(u32 battler) bool32 IsShieldsDownProtected(u32 battler) { return (gBattleMons[battler].ability == ABILITY_SHIELDS_DOWN - && gBattleMons[battler].species == SPECIES_MINIOR); + && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < 6); // Minior is not in core form } u32 IsAbilityStatusProtected(u32 battler) From f0cb6190e00b002d00f8ac921a22943de0e3d757 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 7 Aug 2021 20:56:10 +1200 Subject: [PATCH 041/136] Implement Burmy form change Burmy changes form based on where it last battled. --- include/battle_util.h | 1 + src/battle_main.c | 1 + src/battle_util.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/battle_util.h b/include/battle_util.h index e10305e564..521bb2693e 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -138,6 +138,7 @@ bool32 CanFling(u8 battlerId); bool32 IsTelekinesisBannedSpecies(u16 species); bool32 IsHealBlockPreventingMove(u32 battler, u32 move); bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId); +void DoBurmyFormChange(u32 monId); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_main.c b/src/battle_main.c index 94700bf969..d7fb7f6976 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4879,6 +4879,7 @@ static void HandleEndTurn_FinishBattle(void) { UndoMegaEvolution(i); UndoFormChange(i, B_SIDE_PLAYER, FALSE); + DoBurmyFormChange(i); } gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions; gCB2_AfterEvolution = BattleMainCB2; diff --git a/src/battle_util.c b/src/battle_util.c index 7deebd25e3..19913781dc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8659,3 +8659,43 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability) } return FALSE; } + ++void DoBurmyFormChange(u32 monId) +{ + u16 newSpecies, currSpecies; + s32 sentIn; + struct Pokemon *party = gPlayerParty; + + sentIn = gSentPokesToOpponent[(gBattlerFainted & 2) >> 1]; + currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); + + if ((gSpeciesToNationalPokedexNum[currSpecies - 1] == SPECIES_BURMY) && (gBitTable[monId] & sentIn)) + { + switch (gBattleTerrain) + { + case BATTLE_TERRAIN_GRASS: + case BATTLE_TERRAIN_LONG_GRASS: + case BATTLE_TERRAIN_POND: + case BATTLE_TERRAIN_MOUNTAIN: + case BATTLE_TERRAIN_PLAIN: + newSpecies = SPECIES_BURMY; + break; + case BATTLE_TERRAIN_CAVE: + case BATTLE_TERRAIN_SAND: + newSpecies = SPECIES_BURMY_SANDY_CLOAK; + break; + case BATTLE_TERRAIN_BUILDING: + newSpecies = SPECIES_BURMY_TRASH_CLOAK; + break; + default: // Don't change form if last battle was water-related + newSpecies = SPECIES_NONE; + break; + } + + if (newSpecies != SPECIES_NONE) + { + SetMonData(&party[monId], MON_DATA_SPECIES, &newSpecies); + CalculateMonStats(&party[monId]); + } + } +} From 6c6363f7cf67a9f12a28a0126e3b4d84dafd6935 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 7 Aug 2021 20:59:04 +1200 Subject: [PATCH 042/136] Use form table in species check --- 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 19913781dc..fa5cb5456a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8669,7 +8669,7 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability) sentIn = gSentPokesToOpponent[(gBattlerFainted & 2) >> 1]; currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - if ((gSpeciesToNationalPokedexNum[currSpecies - 1] == SPECIES_BURMY) && (gBitTable[monId] & sentIn)) + if ((GET_BASE_SPECIES_ID(currSpecies) == SPECIES_BURMY) && (gBitTable[monId] & sentIn)) { switch (gBattleTerrain) { From e1ca2af8b3732df237f1025d8eca28c442bdd7f1 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 8 Aug 2021 00:52:27 +1200 Subject: [PATCH 043/136] Update src/battle_util.c Fix copy/paste typo Co-authored-by: LOuroboros --- 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 fa5cb5456a..50a2a62230 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8660,7 +8660,7 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability) return FALSE; } -+void DoBurmyFormChange(u32 monId) +void DoBurmyFormChange(u32 monId) { u16 newSpecies, currSpecies; s32 sentIn; From 30c983d9cac69431e5865ed6559c8c0541ad217f Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 8 Aug 2021 13:14:51 +1200 Subject: [PATCH 044/136] Define Burmy forms in battle engine Title. BE needs these to compile on its own. --- include/constants/battle_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index bf31c77b3b..cdeadfbf7c 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -37,6 +37,9 @@ #define SPECIES_ZYGARDE 0 // 50% #define SPECIES_ZYGARDE_10 10011 // 10 % #define SPECIES_ZYGARDE_COMPLETE 10012 // 100 % + #define SPECIES_BURMY 0 + #define SPECIES_BURMY_SANDY_CLOAK 10013 + #define SPECIES_BURMY_TRASH_CLOAK 10014 #endif // Items with peculiar battle effects. From f050168c55f21bfd44103afffc264b2240a19285 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 12 Aug 2021 13:41:18 -0600 Subject: [PATCH 045/136] 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 94d53f991c..ac9dfb36d0 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 046/136] 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 ac9dfb36d0..f650306d86 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 047/136] 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 07d0c9143e..39fbdab174 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 f0712fc435..e48e4f12ba 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 b7c6424c82..9900990e84 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 048/136] 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 39fbdab174..166957c02d 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 bc298d242f487437d797879889eca2a153f9b444 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 25 Aug 2021 23:15:30 +1200 Subject: [PATCH 049/136] Move mega indicator for lv 100 mons Indicator sprite overlaps the "100" without this. --- src/battle_interface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/battle_interface.c b/src/battle_interface.c index c4fcfe3316..1a6a933a1b 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1519,11 +1519,15 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) { x += sIndicatorPosDoubles[position][0]; y += sIndicatorPosDoubles[position][1]; + if (gBattleMons[battlerId].level >= 100) + x -= 4; } else { x += sIndicatorPosSingles[position][0]; y += sIndicatorPosSingles[position][1]; + if (gBattleMons[battlerId].level >= 100) + x -= 4; } spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0); gSprites[gSprites[gHealthboxSpriteIds[battlerId]].oam.affineParam].hOther_IndicatorSpriteId = spriteId; From 1d1546c7b22c59afb0dd1b6ec519ab8f5623e6ca Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Thu, 26 Aug 2021 19:00:43 +1200 Subject: [PATCH 050/136] Suggested changes --- src/battle_interface.c | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index 1a6a933a1b..26d6fb27f1 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1037,6 +1037,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) { objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); + xPos = 5 * (3 - (objVram - (text + 2))) - 1; } else { @@ -1044,6 +1045,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) text[1] = CHAR_LV_2; objVram = ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); + xPos = 5 * (3 - (objVram - (text + 2))); } xPos = 5 * (3 - (objVram - (text + 2))); @@ -1491,18 +1493,12 @@ void DestroyMegaTriggerSprite(void) gBattleStruct->mega.triggerSpriteId = 0xFF; } -static const s8 sIndicatorPosSingles[][2] = +static const s8 sIndicatorPositions[][2] = { - [B_POSITION_PLAYER_LEFT] = {53, -8}, - [B_POSITION_OPPONENT_LEFT] = {45, -8}, -}; - -static const s8 sIndicatorPosDoubles[][2] = -{ - [B_POSITION_PLAYER_LEFT] = {53, -8}, - [B_POSITION_OPPONENT_LEFT] = {45, -8}, - [B_POSITION_PLAYER_RIGHT] = {53, -8}, - [B_POSITION_OPPONENT_RIGHT] = {45, -8}, + [B_POSITION_PLAYER_LEFT] = {52, -9}, + [B_POSITION_OPPONENT_LEFT] = {44, -9}, + [B_POSITION_PLAYER_RIGHT] = {52, -9}, + [B_POSITION_OPPONENT_RIGHT] = {44, -9}, }; u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) @@ -1515,20 +1511,15 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which) position = GetBattlerPosition(battlerId); GetBattlerHealthboxCoords(battlerId, &x, &y); - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - { - x += sIndicatorPosDoubles[position][0]; - y += sIndicatorPosDoubles[position][1]; - if (gBattleMons[battlerId].level >= 100) - x -= 4; - } - else - { - x += sIndicatorPosSingles[position][0]; - y += sIndicatorPosSingles[position][1]; - if (gBattleMons[battlerId].level >= 100) - x -= 4; - } + + x += sIndicatorPositions[position][0]; + y += sIndicatorPositions[position][1]; + + if (gBattleMons[battlerId].level >= 100) + x -= 4; + else if (gBattleMons[battlerId].level < 10) + x += 5; + spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0); gSprites[gSprites[gHealthboxSpriteIds[battlerId]].oam.affineParam].hOther_IndicatorSpriteId = spriteId; From 6ce122744767ac97694997aa9c90472d977cbb60 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 3 Sep 2021 11:05:11 -0400 Subject: [PATCH 051/136] 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 0d3eb9d50a..762b9d3e53 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 1948161b4f..f72f85d5c5 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 766af072c2..f35a377669 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 3344573fbd..a53a6b0e08 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 0173ca49fe..5f5f2e19bc 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 052/136] 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 5f5f2e19bc..04b5abdddc 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 053/136] 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 762b9d3e53..188a90ee20 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 f72f85d5c5..6e2b2b5dd4 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 a53a6b0e08..576dde83c8 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 04b5abdddc..16f414c5eb 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 054/136] 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 6e2b2b5dd4..91db8af1d7 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 576dde83c8..afc2dc1249 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 16f414c5eb..466ebcfe6b 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 055/136] 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 afc2dc1249..a55bc968b3 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 056/136] 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 188a90ee20..c19812433a 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 a55bc968b3..7cc12b391d 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 057/136] 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 c19812433a..c7256dc7ed 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 7cc12b391d..9f1b0ba933 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 058/136] 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 d47152f7f7..5f79efc57a 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 059/136] 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 adb0c70ad6..81f9cfaf96 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 7d3980de589d0c645c9f31838937b0da463a8611 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 12 Sep 2021 18:33:04 +1200 Subject: [PATCH 060/136] Fix multihit moves vs damage reducing berries The extra waitmessage command is ugly but appears to be needed - if it's moved before the printstring, the message isn't displayed long enough on single hit moves. --- data/battle_scripts_1.s | 1 + src/battle_script_commands.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2d6db5a289..7c37be63c8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7519,6 +7519,7 @@ BattleScript_BerryReduceDmg:: BattleScript_PrintBerryReduceString:: waitmessage B_WAIT_TIME_LONG printstring STRINGID_BERRYDMGREDUCES + waitmessage B_WAIT_TIME_LONG return BattleScript_BerryCureConfusionEnd2:: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 05702aec6b..c7df3406ea 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1967,6 +1967,15 @@ static void Cmd_multihitresultmessage(void) } } gBattlescriptCurrInstr++; + + // Print berry reducing message after result message. + if (gSpecialStatuses[gBattlerTarget].berryReduced + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + { + gSpecialStatuses[gBattlerTarget].berryReduced = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_PrintBerryReduceString; + } } static void Cmd_attackanimation(void) From 95af97593bb18597a462e952026e74c121d576ab Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 14 Sep 2021 11:53:35 -0400 Subject: [PATCH 061/136] 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 4ea8042a71..f0d4f4c973 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 a3f7d027d0..43a941737e 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 f35a377669..a59b930b49 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 aed1dc568d..74995bbf3a 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 0440900697..6ba74177df 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 bc5c7e0e79..ab7db3d88e 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 062/136] 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 14bfe2c388..ac72666908 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 f0d4f4c973..28e9f83278 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 91db8af1d7..ad0c69534d 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 a59b930b49..6ab8df3005 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 6ba74177df..b3f528a00a 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 ab7db3d88e..eb10bc8967 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 063/136] 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 ad0c69534d..4f250c7ea0 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 eb10bc8967..4cec2160af 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 064/136] 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 43a941737e..36646c9fef 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 b3f528a00a..7146840dad 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 4cec2160af..7edc4eadce 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 065/136] 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 7146840dad..5b090b5e49 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 066/136] 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 4f30b3f307..a0e7b9445f 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 344d1c596e..4ddae69907 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 3c21604d80..bec1bf9a84 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 5027e48b97..27b4521f48 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 067/136] 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 27b4521f48..c880c7fddf 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 068/136] 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 f449306a6e..f02dd9a3e2 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 175496ca06..30066438b2 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 d57d2daae8..b8a37704c8 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 069/136] 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 a7263e4bea..202cdbddb5 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 0558e4feb4..e0b466b17e 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 19468f168e..1e9fd918b8 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 8b2a186f1b..9c1061b335 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 aeafd9e2227db86dc5fd63aca0976a5cbf8c4677 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 11:34:01 -0400 Subject: [PATCH 070/136] perish song + prankster interaction --- data/battle_scripts_1.s | 19 ++++++++++++++----- src/battle_script_commands.c | 3 ++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4c41db86ef..a1076e921c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3647,19 +3647,28 @@ BattleScript_EffectPerishSong:: waitanimation printstring STRINGID_FAINTINTHREE waitmessage B_WAIT_TIME_LONG - setbyte sBATTLER, 0 + setbyte gBattlerTarget, 0 BattleScript_PerishSongLoop:: - jumpifability BS_SCRIPTING, ABILITY_SOUNDPROOF, BattleScript_PerishSongNotAffected + jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked + jumpifability BS_ATTACKER, ABILITY_PRANKSTER, BattleScript_PerishSongCheckPrankster + goto BattleScript_PerishSongLoopIncrement +BattleScript_PerishSongCheckPrankster: + jumpiftype BS_TARGET, TYPE_DARK, BattleScript_PerishSongNotAffected BattleScript_PerishSongLoopIncrement:: - addbyte sBATTLER, 1 - jumpifbytenotequal sBATTLER, gBattlersCount, BattleScript_PerishSongLoop + addbyte gBattlerTarget, 1 + jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_PerishSongLoop goto BattleScript_MoveEnd -BattleScript_PerishSongNotAffected:: +BattleScript_PerishSongBlocked:: printstring STRINGID_PKMNSXBLOCKSY2 waitmessage B_WAIT_TIME_LONG goto BattleScript_PerishSongLoopIncrement +BattleScript_PerishSongNotAffected: + printstring STRINGID_ITDOESNTAFFECT + waitmessage B_WAIT_TIME_LONG + goto BattleScript_PerishSongLoopIncrement + BattleScript_EffectSandstorm:: attackcanceler attackstring diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 28e000a7bd..c1da44b2e2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10605,7 +10605,8 @@ static void Cmd_trysetperishsong(void) for (i = 0; i < gBattlersCount; i++) { if (gStatuses3[i] & STATUS3_PERISH_SONG - || gBattleMons[i].ability == ABILITY_SOUNDPROOF) + || gBattleMons[i].ability == ABILITY_SOUNDPROOF + || (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(i, TYPE_DARK))) { notAffectedCount++; } From 2067f563cd66de8342c3c71c4bbca86e7b0bae45 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 11:47:05 -0400 Subject: [PATCH 071/136] cannot block your own prankster elevated perish song --- data/battle_scripts_1.s | 1 + src/battle_script_commands.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a1076e921c..cb450c385e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3650,6 +3650,7 @@ BattleScript_EffectPerishSong:: setbyte gBattlerTarget, 0 BattleScript_PerishSongLoop:: jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked + jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_PerishSongLoopIncrement @ cannot block your own perish song jumpifability BS_ATTACKER, ABILITY_PRANKSTER, BattleScript_PerishSongCheckPrankster goto BattleScript_PerishSongLoopIncrement BattleScript_PerishSongCheckPrankster: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c1da44b2e2..5abc8a9d59 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10606,7 +10606,7 @@ static void Cmd_trysetperishsong(void) { if (gStatuses3[i] & STATUS3_PERISH_SONG || gBattleMons[i].ability == ABILITY_SOUNDPROOF - || (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(i, TYPE_DARK))) + || (i != gBattlerAttacker && GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(i, TYPE_DARK))) { notAffectedCount++; } From a50f03a06b20cd5858e7729aaccc96e8e6e54a63 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 11:53:24 -0400 Subject: [PATCH 072/136] magic bounce overrides prankster blockage --- src/battle_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 6e15aead1d..9f8521e62c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3408,7 +3408,8 @@ u8 AtkCanceller_UnableToUseMove(void) && gBattlerAttacker != gBattlerTarget && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_OPPONENTS_FIELD) && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) - && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE)) + && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE) + && GetBattlerAbility(gBattlerTarget) != ABILITY_MAGIC_BOUNCE) // Magic bounce will bounce back prankster'd status move instead of blocking it { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // don't cancel moves that can hit two targets bc one target might not be protected From ac42b19de7fb4f581c81840ea1fd8937944b9557 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 11:54:27 -0400 Subject: [PATCH 073/136] some formatting fixes --- include/constants/battle_config.h | 2 +- src/battle_util.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 67d3cc5e74..893ed06d1e 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -125,7 +125,7 @@ #define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. #define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. #define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities. -#define B_PRANKSTER_DARK_TYPES GEN_7 // In Gen7, Prankster-elevated status moves do not affect Dark type Pokémon. +#define B_PRANKSTER_DARK_TYPES GEN_7 // In Gen7+, Prankster-elevated status moves do not affect Dark type Pokémon. // Item settings #define B_HP_BERRIES GEN_7 // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. diff --git a/src/battle_util.c b/src/battle_util.c index 9f8521e62c..edf242619d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3418,8 +3418,8 @@ u8 AtkCanceller_UnableToUseMove(void) effect = 1; } #endif - gBattleStruct->atkCancellerTracker++; - break; + gBattleStruct->atkCancellerTracker++; + break; case CANCELLER_END: break; } From c2e0990aabd6fea94f68e61ca15f150ca8e5face Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 13:29:36 -0400 Subject: [PATCH 074/136] fix some merge conflicts --- data/battle_scripts_1.s | 648 ++++----------------- include/constants/battle_move_effects.h | 251 +------- include/constants/battle_script_commands.h | 13 +- 3 files changed, 141 insertions(+), 771 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a496925942..865b1512d2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -18,483 +18,6 @@ .section script_data, "aw", %progbits .align 2 -<<<<<<< HEAD -gBattleScriptsForMoveEffects:: @ 82D86A8 - .4byte BattleScript_EffectHit - .4byte BattleScript_EffectSleep - .4byte BattleScript_EffectPoisonHit - .4byte BattleScript_EffectAbsorb - .4byte BattleScript_EffectBurnHit - .4byte BattleScript_EffectFreezeHit - .4byte BattleScript_EffectParalyzeHit - .4byte BattleScript_EffectExplosion - .4byte BattleScript_EffectDreamEater - .4byte BattleScript_EffectMirrorMove - .4byte BattleScript_EffectAttackUp - .4byte BattleScript_EffectDefenseUp - .4byte BattleScript_EffectSpeedUp - .4byte BattleScript_EffectSpecialAttackUp - .4byte BattleScript_EffectSpecialDefenseUp - .4byte BattleScript_EffectAccuracyUp - .4byte BattleScript_EffectEvasionUp - .4byte BattleScript_EffectSpecialAttackUp3 - .4byte BattleScript_EffectAttackDown - .4byte BattleScript_EffectDefenseDown - .4byte BattleScript_EffectSpeedDown - .4byte BattleScript_EffectSpecialAttackDown - .4byte BattleScript_EffectSpecialDefenseDown - .4byte BattleScript_EffectAccuracyDown - .4byte BattleScript_EffectEvasionDown - .4byte BattleScript_EffectHaze - .4byte BattleScript_EffectBide - .4byte BattleScript_EffectRampage - .4byte BattleScript_EffectRoar - .4byte BattleScript_EffectMultiHit - .4byte BattleScript_EffectConversion - .4byte BattleScript_EffectFlinchHit - .4byte BattleScript_EffectRestoreHp - .4byte BattleScript_EffectToxic - .4byte BattleScript_EffectPayDay - .4byte BattleScript_EffectLightScreen - .4byte BattleScript_EffectTriAttack - .4byte BattleScript_EffectRest - .4byte BattleScript_EffectOHKO - .4byte BattleScript_EffectFusionCombo - .4byte BattleScript_EffectSuperFang - .4byte BattleScript_EffectDragonRage - .4byte BattleScript_EffectTrap - .4byte BattleScript_EffectHealBlock - .4byte BattleScript_EffectDoubleHit - .4byte BattleScript_EffectRecoilIfMiss - .4byte BattleScript_EffectMist - .4byte BattleScript_EffectFocusEnergy - .4byte BattleScript_EffectRecoil25 - .4byte BattleScript_EffectConfuse - .4byte BattleScript_EffectAttackUp2 - .4byte BattleScript_EffectDefenseUp2 - .4byte BattleScript_EffectSpeedUp2 - .4byte BattleScript_EffectSpecialAttackUp2 - .4byte BattleScript_EffectSpecialDefenseUp2 - .4byte BattleScript_EffectAccuracyUp2 - .4byte BattleScript_EffectEvasionUp2 - .4byte BattleScript_EffectTransform - .4byte BattleScript_EffectAttackDown2 - .4byte BattleScript_EffectDefenseDown2 - .4byte BattleScript_EffectSpeedDown2 - .4byte BattleScript_EffectSpecialAttackDown2 - .4byte BattleScript_EffectSpecialDefenseDown2 - .4byte BattleScript_EffectAccuracyDown2 - .4byte BattleScript_EffectEvasionDown2 - .4byte BattleScript_EffectReflect - .4byte BattleScript_EffectPoison - .4byte BattleScript_EffectParalyze - .4byte BattleScript_EffectAttackDownHit - .4byte BattleScript_EffectDefenseDownHit - .4byte BattleScript_EffectSpeedDownHit - .4byte BattleScript_EffectSpecialAttackDownHit - .4byte BattleScript_EffectSpecialDefenseDownHit - .4byte BattleScript_EffectAccuracyDownHit - .4byte BattleScript_EffectEvasionDownHit - .4byte BattleScript_EffectTwoTurnsAttack - .4byte BattleScript_EffectConfuseHit - .4byte BattleScript_EffectTwineedle - .4byte BattleScript_EffectVitalThrow - .4byte BattleScript_EffectSubstitute - .4byte BattleScript_EffectRecharge - .4byte BattleScript_EffectRage - .4byte BattleScript_EffectMimic - .4byte BattleScript_EffectMetronome - .4byte BattleScript_EffectLeechSeed - .4byte BattleScript_EffectDoNothing - .4byte BattleScript_EffectDisable - .4byte BattleScript_EffectLevelDamage - .4byte BattleScript_EffectPsywave - .4byte BattleScript_EffectCounter - .4byte BattleScript_EffectEncore - .4byte BattleScript_EffectPainSplit - .4byte BattleScript_EffectSnore - .4byte BattleScript_EffectConversion2 - .4byte BattleScript_EffectLockOn - .4byte BattleScript_EffectSketch - .4byte BattleScript_EffectHammerArm - .4byte BattleScript_EffectSleepTalk - .4byte BattleScript_EffectDestinyBond - .4byte BattleScript_EffectFlail - .4byte BattleScript_EffectSpite - .4byte BattleScript_EffectFalseSwipe - .4byte BattleScript_EffectHealBell - .4byte BattleScript_EffectAlwaysCrit - .4byte BattleScript_EffectTripleKick - .4byte BattleScript_EffectThief - .4byte BattleScript_EffectMeanLook - .4byte BattleScript_EffectNightmare - .4byte BattleScript_EffectMinimize - .4byte BattleScript_EffectCurse - .4byte BattleScript_EffectHealingWish - .4byte BattleScript_EffectProtect - .4byte BattleScript_EffectSpikes - .4byte BattleScript_EffectForesight - .4byte BattleScript_EffectPerishSong - .4byte BattleScript_EffectSandstorm - .4byte BattleScript_EffectEndure - .4byte BattleScript_EffectRollout - .4byte BattleScript_EffectSwagger - .4byte BattleScript_EffectFuryCutter - .4byte BattleScript_EffectAttract - .4byte BattleScript_EffectReturn - .4byte BattleScript_EffectPresent - .4byte BattleScript_EffectFrustration - .4byte BattleScript_EffectSafeguard - .4byte BattleScript_EffectMagnitude - .4byte BattleScript_EffectBatonPass - .4byte BattleScript_EffectPursuit - .4byte BattleScript_EffectRapidSpin - .4byte BattleScript_EffectSonicboom - .4byte BattleScript_EffectCaptivate - .4byte BattleScript_EffectMorningSun - .4byte BattleScript_EffectSynthesis - .4byte BattleScript_EffectMoonlight - .4byte BattleScript_EffectHiddenPower - .4byte BattleScript_EffectRainDance - .4byte BattleScript_EffectSunnyDay - .4byte BattleScript_EffectDefenseUpHit - .4byte BattleScript_EffectAttackUpHit - .4byte BattleScript_EffectAllStatsUpHit - .4byte BattleScript_EffectFellStinger - .4byte BattleScript_EffectBellyDrum - .4byte BattleScript_EffectPsychUp - .4byte BattleScript_EffectMirrorCoat - .4byte BattleScript_EffectSkullBash - .4byte BattleScript_EffectTwister - .4byte BattleScript_EffectEarthquake - .4byte BattleScript_EffectFutureSight - .4byte BattleScript_EffectGust - .4byte BattleScript_EffectStomp - .4byte BattleScript_EffectSolarbeam - .4byte BattleScript_EffectThunder - .4byte BattleScript_EffectTeleport - .4byte BattleScript_EffectBeatUp - .4byte BattleScript_EffectSemiInvulnerable - .4byte BattleScript_EffectDefenseCurl - .4byte BattleScript_EffectSoftboiled - .4byte BattleScript_EffectFakeOut - .4byte BattleScript_EffectUproar - .4byte BattleScript_EffectStockpile - .4byte BattleScript_EffectSpitUp - .4byte BattleScript_EffectSwallow - .4byte BattleScript_EffectWorrySeed - .4byte BattleScript_EffectHail - .4byte BattleScript_EffectTorment - .4byte BattleScript_EffectFlatter - .4byte BattleScript_EffectWillOWisp - .4byte BattleScript_EffectMemento - .4byte BattleScript_EffectFacade - .4byte BattleScript_EffectFocusPunch - .4byte BattleScript_EffectSmellingsalt - .4byte BattleScript_EffectFollowMe - .4byte BattleScript_EffectNaturePower - .4byte BattleScript_EffectCharge - .4byte BattleScript_EffectTaunt - .4byte BattleScript_EffectHelpingHand - .4byte BattleScript_EffectTrick - .4byte BattleScript_EffectRolePlay - .4byte BattleScript_EffectWish - .4byte BattleScript_EffectAssist - .4byte BattleScript_EffectIngrain - .4byte BattleScript_EffectSuperpower - .4byte BattleScript_EffectMagicCoat - .4byte BattleScript_EffectRecycle - .4byte BattleScript_EffectRevenge - .4byte BattleScript_EffectBrickBreak - .4byte BattleScript_EffectYawn - .4byte BattleScript_EffectKnockOff - .4byte BattleScript_EffectEndeavor - .4byte BattleScript_EffectEruption - .4byte BattleScript_EffectSkillSwap - .4byte BattleScript_EffectImprison - .4byte BattleScript_EffectRefresh - .4byte BattleScript_EffectGrudge - .4byte BattleScript_EffectSnatch - .4byte BattleScript_EffectLowKick - .4byte BattleScript_EffectSecretPower - .4byte BattleScript_EffectRecoil33 - .4byte BattleScript_EffectTeeterDance - .4byte BattleScript_EffectHitEscape - .4byte BattleScript_EffectMudSport - .4byte BattleScript_EffectPoisonFang - .4byte BattleScript_EffectWeatherBall - .4byte BattleScript_EffectOverheat - .4byte BattleScript_EffectTickle - .4byte BattleScript_EffectCosmicPower - .4byte BattleScript_EffectSkyUppercut - .4byte BattleScript_EffectBulkUp - .4byte BattleScript_EffectPlaceholder - .4byte BattleScript_EffectWaterSport - .4byte BattleScript_EffectCalmMind - .4byte BattleScript_EffectDragonDance - .4byte BattleScript_EffectCamouflage - .4byte BattleScript_EffectPledge - .4byte BattleScript_EffectFling - .4byte BattleScript_EffectNaturalGift - .4byte BattleScript_EffectWakeUpSlap - .4byte BattleScript_EffectWringOut - .4byte BattleScript_EffectHex - .4byte BattleScript_EffectAssurance - .4byte BattleScript_EffectTrump_card - .4byte BattleScript_EffectAcrobatics - .4byte BattleScript_EffectHeatCrash - .4byte BattleScript_EffectPunishment - .4byte BattleScript_EffectStoredPower - .4byte BattleScript_EffectElectroBall - .4byte BattleScript_EffectGyroBall - .4byte BattleScript_EffectEchoedVoice - .4byte BattleScript_EffectPayback - .4byte BattleScript_EffectRound - .4byte BattleScript_EffectBrine - .4byte BattleScript_EffectVenoshock - .4byte BattleScript_EffectRetalitate - .4byte BattleScript_EffectBulldoze - .4byte BattleScript_EffectFoulPlay - .4byte BattleScript_EffectPsyshock - .4byte BattleScript_EffectRoost - .4byte BattleScript_EffectGravity - .4byte BattleScript_EffectMircleEye - .4byte BattleScript_EffectTailwind - .4byte BattleScript_EffectEmbargo - .4byte BattleScript_EffectAquaRing - .4byte BattleScript_EffectTrickRoom - .4byte BattleScript_EffectWonderRoom - .4byte BattleScript_EffectMagicRoom - .4byte BattleScript_EffectMagnetRise - .4byte BattleScript_EffectToxicSpikes - .4byte BattleScript_EffectGastroAcid - .4byte BattleScript_EffectStealthRock - .4byte BattleScript_EffectTelekinesis - .4byte BattleScript_EffectPowerSwap - .4byte BattleScript_EffectGuardSwap - .4byte BattleScript_EffectHeartSwap - .4byte BattleScript_EffectPowerSplit - .4byte BattleScript_EffectGuardSplit - .4byte BattleScript_EffectStickyWeb - .4byte BattleScript_EffectMetalBurst - .4byte BattleScript_EffectLuckyChant - .4byte BattleScript_EffectSuckerPunch - .4byte BattleScript_EffectSpecialDefenseDownHit2 - .4byte BattleScript_EffectSimpleBeam - .4byte BattleScript_EffectEntrainment - .4byte BattleScript_EffectHealPulse - .4byte BattleScript_EffectQuash - .4byte BattleScript_EffectIonDeluge - .4byte BattleScript_EffectFreezeDry - .4byte BattleScript_EffectTopsyTurvy - .4byte BattleScript_EffectMistyTerrain - .4byte BattleScript_EffectGrassyTerrain - .4byte BattleScript_EffectElectricTerrain - .4byte BattleScript_EffectPsychicTerrain - .4byte BattleScript_EffectAttackAccUp - .4byte BattleScript_EffectAttackSpAttackUp - .4byte BattleScript_EffectHurricane - .4byte BattleScript_EffectTwoTypedMove - .4byte BattleScript_EffectMeFirst - .4byte BattleScript_EffectSpeedUpHit - .4byte BattleScript_EffectQuiverDance - .4byte BattleScript_EffectCoil - .4byte BattleScript_EffectElectrify - .4byte BattleScript_EffectScald - .4byte BattleScript_EffectReflectType - .4byte BattleScript_EffectSoak - .4byte BattleScript_EffectGrowth - .4byte BattleScript_EffectCloseCombat - .4byte BattleScript_EffectLastResort - .4byte BattleScript_EffectRecoil33WithStatus - .4byte BattleScript_EffectFlinchWithStatus - .4byte BattleScript_EffectRecoil50 - .4byte BattleScript_EffectShellSmash - .4byte BattleScript_EffectShiftGear - .4byte BattleScript_EffectDefenseUp3 - .4byte BattleScript_EffectNobleRoar - .4byte BattleScript_EffectVenomDrench - .4byte BattleScript_EffectToxicThread - .4byte BattleScript_EffectClearSmog - .4byte BattleScript_EffectHitSwitchTarget - .4byte BattleScript_EffectFinalGambit - .4byte BattleScript_EffectChangeTypeOnItem - .4byte BattleScript_EffectAutotomize - .4byte BattleScript_EffectCopycat - .4byte BattleScript_EffectDefog - .4byte BattleScript_EffectHitEnemyHealAlly - .4byte BattleScript_EffectSmackDown - .4byte BattleScript_EffectSynchronoise - .4byte BattleScript_EffectPsychoShift - .4byte BattleScript_EffectPowerTrick - .4byte BattleScript_EffectFlameBurst - .4byte BattleScript_EffectAfterYou - .4byte BattleScript_EffectBestow - .4byte BattleScript_EffectRototiller - .4byte BattleScript_EffectFlowerShield - .4byte BattleScript_EffectHitPreventEscape - .4byte BattleScript_EffectSpeedSwap - .4byte BattleScript_EffectDefenseUp2Hit - .4byte BattleScript_EffectRevelationDance - .4byte BattleScript_EffectAuroraVeil - .4byte BattleScript_EffectThirdType - .4byte BattleScript_EffectFeint - .4byte BattleScript_EffectSparklingAria - .4byte BattleScript_EffectAcupressure - .4byte BattleScript_EffectAromaticMist - .4byte BattleScript_EffectPowder - .4byte BattleScript_EffectSpAtkUpHit - .4byte BattleScript_EffectBelch - .4byte BattleScript_EffectPartingShot - .4byte BattleScript_EffectSpectralThief - .4byte BattleScript_EffectVCreate - .4byte BattleScript_EffectMatBlock - .4byte BattleScript_EffectStompingTantrum - .4byte BattleScript_EffectCoreEnforcer - .4byte BattleScript_EffectInstruct - .4byte BattleScript_EffectThroatChop - .4byte BattleScript_EffectLaserFocus - .4byte BattleScript_EffectMagneticFlux - .4byte BattleScript_EffectGearUp - .4byte BattleScript_EffectIncinerate - .4byte BattleScript_EffectBugBite - .4byte BattleScript_EffectStrengthSap - .4byte BattleScript_EffectMindBlown - .4byte BattleScript_EffectPurify - .4byte BattleScript_EffectBurnUp - .4byte BattleScript_EffectShoreUp - .4byte BattleScript_EffectGeomancy - .4byte BattleScript_EffectFairyLock - .4byte BattleScript_EffectAllySwitch - .4byte BattleScript_EffectSleepHit - .4byte BattleScript_EffectAttackerDefenseDownHit - .4byte BattleScript_EffectBodyPress - .4byte BattleScript_EffectEerieSpell - .4byte BattleScript_EffectJungleHealing - .4byte BattleScript_EffectCoaching - .4byte BattleScript_EffectLashOut - .4byte BattleScript_EffectGrassyGlide - .4byte BattleScript_EffectRemoveTerrain - .4byte BattleScript_EffectDynamaxDoubleDmg - .4byte BattleScript_EffectDecorate - .4byte BattleScript_EffectSnipeShot - .4byte BattleScript_EffectTripleHit - -BattleScript_EffectDecorate: - attackcanceler - attackstring - ppreduce - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, 12, BattleScript_DecorateBoost - goto BattleScript_ButItFailed -BattleScript_DecorateBoost: - attackanimation - waitanimation - setbyte sSTAT_ANIM_PLAYED, FALSE - playstatchangeanimation BS_TARGET, BIT_ATK | BIT_SPATK, 0x0 - setstatchanger STAT_ATK, 2, FALSE - statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_DecorateBoostSpAtk - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_DecorateBoostSpAtk - printfromtable gStatUpStringIds - waitmessage 0x40 -BattleScript_DecorateBoostSpAtk: - setstatchanger STAT_SPATK, 2, FALSE - statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd - printfromtable gStatUpStringIds - waitmessage 0x40 - goto BattleScript_MoveEnd - -BattleScript_EffectRemoveTerrain: - attackcanceler - attackstring - ppreduce - jumpifword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ButItFailed - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage 0x40 - resultmessage - waitmessage 0x40 - removeterrain - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_MoveEnd - printfromtable gTerrainEndingStringIds - waitmessage 0x40 - playanimation BS_ATTACKER, B_ANIM_RESTORE_BG, NULL - tryfaintmon BS_TARGET, FALSE, NULL - goto BattleScript_MoveEnd - -BattleScript_EffectCoaching: - attackcanceler - attackstring - ppreduce - jumpifnoally BS_ATTACKER, BattleScript_ButItFailed - copybyte gBattlerTarget, gBattlerAttacker - setallytonexttarget EffectCoaching_CheckAllyStats - goto BattleScript_ButItFailed -EffectCoaching_CheckAllyStats: - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_CoachingWorks - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 12, BattleScript_CoachingWorks - goto BattleScript_ButItFailed @ ally at max atk, def -BattleScript_CoachingWorks: - attackanimation - waitanimation - setbyte sSTAT_ANIM_PLAYED, FALSE - playstatchangeanimation BS_TARGET, BIT_ATK | BIT_DEF, 0x0 - setstatchanger STAT_ATK, 1, FALSE - statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_CoachingBoostDef - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_CoachingBoostDef - printfromtable gStatUpStringIds - waitmessage 0x40 -BattleScript_CoachingBoostDef: - setstatchanger STAT_DEF, 1, FALSE - statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd - printfromtable gStatUpStringIds - waitmessage 0x40 - goto BattleScript_MoveEnd - -BattleScript_EffectJungleHealing: - attackcanceler - attackstring - ppreduce - jumpifteamhealthy BS_ATTACKER, BattleScript_ButItFailed - attackanimation - waitanimation - copybyte gBattlerTarget, gBattlerAttacker - setbyte gBattleCommunication, 0 -JungleHealing_RestoreTargetHealth: - copybyte gBattlerAttacker, gBattlerTarget - tryhealquarterhealth BS_TARGET, BattleScript_JungleHealing_TryCureStatus - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - printstring STRINGID_PKMNREGAINEDHEALTH - waitmessage 0x40 -BattleScript_JungleHealing_TryCureStatus: - jumpifmove MOVE_LIFE_DEW, BattleScript_JungleHealingTryRestoreAlly @ life dew only heals - jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_JungleHealingCureStatus - goto BattleScript_JungleHealingTryRestoreAlly -BattleScript_JungleHealingCureStatus: - curestatus BS_TARGET - updatestatusicon BS_TARGET - printstring STRINGID_PKMNSTATUSNORMAL - waitmessage 0x40 -BattleScript_JungleHealingTryRestoreAlly: - jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd - addbyte gBattleCommunication, 1 - jumpifnoally BS_TARGET, BattleScript_MoveEnd - setallytonexttarget JungleHealing_RestoreTargetHealth - goto BattleScript_MoveEnd -======= gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHit @ EFFECT_HIT .4byte BattleScript_EffectSleep @ EFFECT_SLEEP @@ -846,7 +369,131 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectSleepHit @ EFFECT_SLEEP_HIT .4byte BattleScript_EffectAttackerDefenseDownHit @ EFFECT_ATTACKER_DEFENSE_DOWN_HIT .4byte BattleScript_EffectHit @ EFFECT_BODY_PRESS ->>>>>>> 0cd7f3ffcde00002691719ae33b4fa0516662acf + .4byte BattleScript_EffectEerieSpell @ EFFECT_EERIE_SPELL + .4byte BattleScript_EffectJungleHealing @ EFFECT_JUNGLE_HEALING + .4byte BattleScript_EffectCoaching @ EFFECT_COACHING + .4byte BattleScript_EffectHit @ EFFECT_LASH_OUT + .4byte BattleScript_EffectHit @ EFFECT_GRASSY_GLIDE + .4byte BattleScript_EffectRemoveTerrain @ EFFECT_REMOVE_TERRAIN + .4byte BattleScript_EffectHit @ EFFECT_DYNAMAX_DOUBLE_DMG + .4byte BattleScript_EffectDecorate @ EFFECT_DECORATE + .4byte BattleScript_EffectHit @ EFFECT_SNIPE_SHOT + .4byte BattleScript_EffectTripleHit @ EFFECT_TRIPLE_HIT + +BattleScript_EffectDecorate: + attackcanceler + attackstring + ppreduce + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, 12, BattleScript_DecorateBoost + goto BattleScript_ButItFailed +BattleScript_DecorateBoost: + attackanimation + waitanimation + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_TARGET, BIT_ATK | BIT_SPATK, 0x0 + setstatchanger STAT_ATK, 2, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_DecorateBoostSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_DecorateBoostSpAtk + printfromtable gStatUpStringIds + waitmessage 0x40 +BattleScript_DecorateBoostSpAtk: + setstatchanger STAT_SPATK, 2, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd + printfromtable gStatUpStringIds + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_EffectRemoveTerrain: + attackcanceler + attackstring + ppreduce + jumpifword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ButItFailed + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + resultmessage + waitmessage 0x40 + removeterrain + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_MoveEnd + printfromtable gTerrainEndingStringIds + waitmessage 0x40 + playanimation BS_ATTACKER, B_ANIM_RESTORE_BG, NULL + tryfaintmon BS_TARGET, FALSE, NULL + goto BattleScript_MoveEnd + +BattleScript_EffectCoaching: + attackcanceler + attackstring + ppreduce + jumpifnoally BS_ATTACKER, BattleScript_ButItFailed + copybyte gBattlerTarget, gBattlerAttacker + setallytonexttarget EffectCoaching_CheckAllyStats + goto BattleScript_ButItFailed +EffectCoaching_CheckAllyStats: + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_CoachingWorks + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 12, BattleScript_CoachingWorks + goto BattleScript_ButItFailed @ ally at max atk, def +BattleScript_CoachingWorks: + attackanimation + waitanimation + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_TARGET, BIT_ATK | BIT_DEF, 0x0 + setstatchanger STAT_ATK, 1, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_CoachingBoostDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_CoachingBoostDef + printfromtable gStatUpStringIds + waitmessage 0x40 +BattleScript_CoachingBoostDef: + setstatchanger STAT_DEF, 1, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd + printfromtable gStatUpStringIds + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_EffectJungleHealing: + attackcanceler + attackstring + ppreduce + jumpifteamhealthy BS_ATTACKER, BattleScript_ButItFailed + attackanimation + waitanimation + copybyte gBattlerTarget, gBattlerAttacker + setbyte gBattleCommunication, 0 +JungleHealing_RestoreTargetHealth: + copybyte gBattlerAttacker, gBattlerTarget + tryhealquarterhealth BS_TARGET, BattleScript_JungleHealing_TryCureStatus + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + printstring STRINGID_PKMNREGAINEDHEALTH + waitmessage 0x40 +BattleScript_JungleHealing_TryCureStatus: + jumpifmove MOVE_LIFE_DEW, BattleScript_JungleHealingTryRestoreAlly @ life dew only heals + jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_JungleHealingCureStatus + goto BattleScript_JungleHealingTryRestoreAlly +BattleScript_JungleHealingCureStatus: + curestatus BS_TARGET + updatestatusicon BS_TARGET + printstring STRINGID_PKMNSTATUSNORMAL + waitmessage 0x40 +BattleScript_JungleHealingTryRestoreAlly: + jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd + addbyte gBattleCommunication, 1 + jumpifnoally BS_TARGET, BattleScript_MoveEnd + setallytonexttarget JungleHealing_RestoreTargetHealth + goto BattleScript_MoveEnd BattleScript_EffectAttackerDefenseDownHit: setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN @@ -2495,49 +2142,6 @@ BattleScript_EffectPlaceholder: goto BattleScript_MoveEnd BattleScript_EffectHit:: -<<<<<<< HEAD -BattleScript_EffectLowKick: -BattleScript_EffectFlail: -BattleScript_EffectFacade: -BattleScript_EffectRevenge: -BattleScript_EffectReturn: -BattleScript_EffectFrustration: -BattleScript_EffectEruption: -BattleScript_EffectPledge: -BattleScript_EffectFling: -BattleScript_EffectWringOut: -BattleScript_EffectHex: -BattleScript_EffectAssurance: -BattleScript_EffectTrump_card: -BattleScript_EffectAcrobatics: -BattleScript_EffectHeatCrash: -BattleScript_EffectPunishment: -BattleScript_EffectStoredPower: -BattleScript_EffectElectroBall: -BattleScript_EffectGyroBall: -BattleScript_EffectEchoedVoice: -BattleScript_EffectPayback: -BattleScript_EffectRound: -BattleScript_EffectBrine: -BattleScript_EffectVenoshock: -BattleScript_EffectRetalitate: -BattleScript_EffectFoulPlay: -BattleScript_EffectPsyshock: -BattleScript_EffectWeatherBall: -BattleScript_EffectHiddenPower: -BattleScript_EffectTwoTypedMove: -BattleScript_EffectChangeTypeOnItem: -BattleScript_EffectFusionCombo: -BattleScript_EffectRevelationDance: -BattleScript_EffectBelch: -BattleScript_EffectBodyPress: -BattleScript_EffectLashOut: -BattleScript_EffectGrassyGlide: -BattleScript_EffectDynamaxDoubleDmg: -BattleScript_EffectSnipeShot: - -======= ->>>>>>> 0cd7f3ffcde00002691719ae33b4fa0516662acf BattleScript_HitFromAtkCanceler:: attackcanceler BattleScript_HitFromAccCheck:: @@ -8544,5 +8148,3 @@ BattleScript_StickyBarbTransfer:: waitmessage B_WAIT_TIME_LONG removeitem BS_TARGET return - ->>>>>>> 0cd7f3ffcde00002691719ae33b4fa0516662acf diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index e7249f11f6..760ee66fd2 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -126,244 +126,6 @@ #define EFFECT_PRESENT 122 #define EFFECT_FRUSTRATION 123 #define EFFECT_SAFEGUARD 124 -<<<<<<< HEAD -#define EFFECT_MAGNITUDE 125 -#define EFFECT_BATON_PASS 126 -#define EFFECT_PURSUIT 127 -#define EFFECT_RAPID_SPIN 128 -#define EFFECT_SONICBOOM 129 -#define EFFECT_CAPTIVATE 130 -#define EFFECT_MORNING_SUN 131 -#define EFFECT_SYNTHESIS 132 -#define EFFECT_MOONLIGHT 133 -#define EFFECT_HIDDEN_POWER 134 -#define EFFECT_RAIN_DANCE 135 -#define EFFECT_SUNNY_DAY 136 -#define EFFECT_DEFENSE_UP_HIT 137 -#define EFFECT_ATTACK_UP_HIT 138 -#define EFFECT_ALL_STATS_UP_HIT 139 -#define EFFECT_FELL_STINGER 140 -#define EFFECT_BELLY_DRUM 141 -#define EFFECT_PSYCH_UP 142 -#define EFFECT_MIRROR_COAT 143 -#define EFFECT_SKULL_BASH 144 -#define EFFECT_TWISTER 145 -#define EFFECT_EARTHQUAKE 146 -#define EFFECT_FUTURE_SIGHT 147 -#define EFFECT_GUST 148 -#define EFFECT_FLINCH_MINIMIZE_HIT 149 -#define EFFECT_SOLARBEAM 150 -#define EFFECT_THUNDER 151 -#define EFFECT_TELEPORT 152 -#define EFFECT_BEAT_UP 153 -#define EFFECT_SEMI_INVULNERABLE 154 -#define EFFECT_DEFENSE_CURL 155 -#define EFFECT_SOFTBOILED 156 -#define EFFECT_FAKE_OUT 157 -#define EFFECT_UPROAR 158 -#define EFFECT_STOCKPILE 159 -#define EFFECT_SPIT_UP 160 -#define EFFECT_SWALLOW 161 -#define EFFECT_WORRY_SEED 162 -#define EFFECT_HAIL 163 -#define EFFECT_TORMENT 164 -#define EFFECT_FLATTER 165 -#define EFFECT_WILL_O_WISP 166 -#define EFFECT_MEMENTO 167 -#define EFFECT_FACADE 168 -#define EFFECT_FOCUS_PUNCH 169 -#define EFFECT_SMELLINGSALT 170 -#define EFFECT_FOLLOW_ME 171 -#define EFFECT_NATURE_POWER 172 -#define EFFECT_CHARGE 173 -#define EFFECT_TAUNT 174 -#define EFFECT_HELPING_HAND 175 -#define EFFECT_TRICK 176 -#define EFFECT_ROLE_PLAY 177 -#define EFFECT_WISH 178 -#define EFFECT_ASSIST 179 -#define EFFECT_INGRAIN 180 -#define EFFECT_SUPERPOWER 181 -#define EFFECT_MAGIC_COAT 182 -#define EFFECT_RECYCLE 183 -#define EFFECT_REVENGE 184 -#define EFFECT_BRICK_BREAK 185 -#define EFFECT_YAWN 186 -#define EFFECT_KNOCK_OFF 187 -#define EFFECT_ENDEAVOR 188 -#define EFFECT_ERUPTION 189 -#define EFFECT_SKILL_SWAP 190 -#define EFFECT_IMPRISON 191 -#define EFFECT_REFRESH 192 -#define EFFECT_GRUDGE 193 -#define EFFECT_SNATCH 194 -#define EFFECT_LOW_KICK 195 -#define EFFECT_SECRET_POWER 196 -#define EFFECT_RECOIL_33 197 -#define EFFECT_TEETER_DANCE 198 -#define EFFECT_HIT_ESCAPE 199 -#define EFFECT_MUD_SPORT 200 -#define EFFECT_POISON_FANG 201 -#define EFFECT_WEATHER_BALL 202 -#define EFFECT_OVERHEAT 203 -#define EFFECT_TICKLE 204 -#define EFFECT_COSMIC_POWER 205 -#define EFFECT_SKY_UPPERCUT 206 -#define EFFECT_BULK_UP 207 -#define EFFECT_PLACEHOLDER 208 -#define EFFECT_WATER_SPORT 209 -#define EFFECT_CALM_MIND 210 -#define EFFECT_DRAGON_DANCE 211 -#define EFFECT_CAMOUFLAGE 212 - -// -#define EFFECT_PLEDGE 213 -#define EFFECT_FLING 214 -#define EFFECT_NATURAL_GIFT 215 -#define EFFECT_WAKE_UP_SLAP 216 -#define EFFECT_WRING_OUT 217 -#define EFFECT_HEX 218 -#define EFFECT_ASSURANCE 219 -#define EFFECT_TRUMP_CARD 220 -#define EFFECT_ACROBATICS 221 -#define EFFECT_HEAT_CRASH 222 -#define EFFECT_PUNISHMENT 223 -#define EFFECT_STORED_POWER 224 -#define EFFECT_ELECTRO_BALL 225 -#define EFFECT_GYRO_BALL 226 -#define EFFECT_ECHOED_VOICE 227 -#define EFFECT_PAYBACK 228 -#define EFFECT_ROUND 229 -#define EFFECT_BRINE 230 -#define EFFECT_VENOSHOCK 231 -#define EFFECT_RETALITATE 232 -#define EFFECT_BULLDOZE 233 -#define EFFECT_FOUL_PLAY 234 -#define EFFECT_PSYSHOCK 235 -#define EFFECT_ROOST 236 -#define EFFECT_GRAVITY 237 -#define EFFECT_MIRACLE_EYE 238 -#define EFFECT_TAILWIND 239 -#define EFFECT_EMBARGO 240 -#define EFFECT_AQUA_RING 241 -#define EFFECT_TRICK_ROOM 242 -#define EFFECT_WONDER_ROOM 243 -#define EFFECT_MAGIC_ROOM 244 -#define EFFECT_MAGNET_RISE 245 -#define EFFECT_TOXIC_SPIKES 246 -#define EFFECT_GASTRO_ACID 247 -#define EFFECT_STEALTH_ROCK 248 -#define EFFECT_TELEKINESIS 249 -#define EFFECT_POWER_SWAP 250 -#define EFFECT_GUARD_SWAP 251 -#define EFFECT_HEART_SWAP 252 -#define EFFECT_POWER_SPLIT 253 -#define EFFECT_GUARD_SPLIT 254 -#define EFFECT_STICKY_WEB 255 -#define EFFECT_METAL_BURST 256 -#define EFFECT_LUCKY_CHANT 257 -#define EFFECT_SUCKER_PUNCH 258 -#define EFFECT_SPECIAL_DEFENSE_DOWN_HIT_2 259 -#define EFFECT_SIMPLE_BEAM 260 -#define EFFECT_ENTRAINMENT 261 -#define EFFECT_HEAL_PULSE 262 -#define EFFECT_QUASH 263 -#define EFFECT_ION_DELUGE 264 -#define EFFECT_FREEZE_DRY 265 -#define EFFECT_TOPSY_TURVY 266 -#define EFFECT_MISTY_TERRAIN 267 -#define EFFECT_GRASSY_TERRAIN 268 -#define EFFECT_ELECTRIC_TERRAIN 269 -#define EFFECT_PSYCHIC_TERRAIN 270 -#define EFFECT_ATTACK_ACCURACY_UP 271 -#define EFFECT_ATTACK_SPATK_UP 272 -#define EFFECT_HURRICANE 273 -#define EFFECT_TWO_TYPED_MOVE 274 -#define EFFECT_ME_FIRST 275 -#define EFFECT_SPEED_UP_HIT 276 -#define EFFECT_QUIVER_DANCE 277 -#define EFFECT_COIL 278 -#define EFFECT_ELECTRIFY 279 -#define EFFECT_SCALD 280 -#define EFFECT_REFLECT_TYPE 281 -#define EFFECT_SOAK 282 -#define EFFECT_GROWTH 283 -#define EFFECT_CLOSE_COMBAT 284 -#define EFFECT_LAST_RESORT 285 -#define EFFECT_RECOIL_33_STATUS 286 -#define EFFECT_FLINCH_STATUS 287 -#define EFFECT_RECOIL_50 288 -#define EFFECT_SHELL_SMASH 289 -#define EFFECT_SHIFT_GEAR 290 -#define EFFECT_DEFENSE_UP_3 291 -#define EFFECT_NOBLE_ROAR 292 -#define EFFECT_VENOM_DRENCH 293 -#define EFFECT_TOXIC_THREAD 294 -#define EFFECT_CLEAR_SMOG 295 -#define EFFECT_HIT_SWITCH_TARGET 296 -#define EFFECT_FINAL_GAMBIT 297 -#define EFFECT_CHANGE_TYPE_ON_ITEM 298 -#define EFFECT_AUTOTOMIZE 299 -#define EFFECT_COPYCAT 300 -#define EFFECT_DEFOG 301 -#define EFFECT_HIT_ENEMY_HEAL_ALLY 302 -#define EFFECT_SMACK_DOWN 303 -#define EFFECT_SYNCHRONOISE 304 -#define EFFECT_PSYCHO_SHIFT 305 -#define EFFECT_POWER_TRICK 306 -#define EFFECT_FLAME_BURST 307 -#define EFFECT_AFTER_YOU 308 -#define EFFECT_BESTOW 309 -#define EFFECT_ROTOTILLER 310 -#define EFFECT_FLOWER_SHIELD 311 -#define EFFECT_HIT_PREVENT_ESCAPE 312 -#define EFFECT_SPEED_SWAP 313 -#define EFFECT_DEFENSE_UP2_HIT 314 -#define EFFECT_REVELATION_DANCE 315 -#define EFFECT_AURORA_VEIL 316 -#define EFFECT_THIRD_TYPE 317 -#define EFFECT_FEINT 318 -#define EFFECT_SPARKLING_ARIA 319 -#define EFFECT_ACUPRESSURE 320 -#define EFFECT_AROMATIC_MIST 321 -#define EFFECT_POWDER 322 -#define EFFECT_SP_ATTACK_UP_HIT 323 -#define EFFECT_BELCH 324 -#define EFFECT_PARTING_SHOT 325 -#define EFFECT_SPECTRAL_THIEF 326 -#define EFFECT_V_CREATE 327 -#define EFFECT_MAT_BLOCK 328 -#define EFFECT_STOMPING_TANTRUM 329 -#define EFFECT_CORE_ENFORCER 330 -#define EFFECT_INSTRUCT 331 -#define EFFECT_THROAT_CHOP 332 -#define EFFECT_LASER_FOCUS 333 -#define EFFECT_MAGNETIC_FLUX 334 -#define EFFECT_GEAR_UP 335 -#define EFFECT_INCINERATE 336 -#define EFFECT_BUG_BITE 337 -#define EFFECT_STRENGTH_SAP 338 -#define EFFECT_MIND_BLOWN 339 -#define EFFECT_PURIFY 340 -#define EFFECT_BURN_UP 341 -#define EFFECT_SHORE_UP 342 -#define EFFECT_GEOMANCY 343 -#define EFFECT_FAIRY_LOCK 344 -#define EFFECT_ALLY_SWITCH 345 -#define EFFECT_SLEEP_HIT 346 -#define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 347 -#define EFFECT_BODY_PRESS 348 -#define EFFECT_EERIE_SPELL 349 -#define EFFECT_JUNGLE_HEALING 350 -#define EFFECT_COACHING 351 -#define EFFECT_LASH_OUT 352 -#define EFFECT_GRASSY_GLIDE 353 -#define EFFECT_REMOVE_TERRAIN 354 -#define EFFECT_DYNAMAX_DOUBLE_DMG 355 -#define EFFECT_DECORATE 356 -#define EFFECT_SNIPE_SHOT 357 -#define EFFECT_TRIPLE_HIT 358 -======= #define EFFECT_UNUSED_125 125 #define EFFECT_MAGNITUDE 126 #define EFFECT_BATON_PASS 127 @@ -591,8 +353,17 @@ #define EFFECT_SLEEP_HIT 347 #define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 348 #define EFFECT_BODY_PRESS 349 ->>>>>>> 0cd7f3ffcde00002691719ae33b4fa0516662acf +#define EFFECT_EERIE_SPELL 350 +#define EFFECT_JUNGLE_HEALING 351 +#define EFFECT_COACHING 352 +#define EFFECT_LASH_OUT 353 +#define EFFECT_GRASSY_GLIDE 354 +#define EFFECT_REMOVE_TERRAIN 355 +#define EFFECT_DYNAMAX_DOUBLE_DMG 356 +#define EFFECT_DECORATE 357 +#define EFFECT_SNIPE_SHOT 358 +#define EFFECT_TRIPLE_HIT 359 -#define NUM_BATTLE_MOVE_EFFECTS 359 +#define NUM_BATTLE_MOVE_EFFECTS 360 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index f9af607656..e6c806784f 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -173,15 +173,12 @@ #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 -<<<<<<< HEAD -#define VARIOUS_EERIE_SPELL_PP_REDUCE 105 -#define VARIOUS_JUMP_IF_TEAM_HEALTHY 106 -#define VARIOUS_TRY_HEAL_QUARTER_HP 107 -#define VARIOUS_REMOVE_TERRAIN 108 -#define VARIOUS_JUMP_IF_OBSTRUCT 109 -======= #define VARIOUS_MOVEEND_ITEM_EFFECTS 105 ->>>>>>> 0cd7f3ffcde00002691719ae33b4fa0516662acf +#define VARIOUS_EERIE_SPELL_PP_REDUCE 106 +#define VARIOUS_JUMP_IF_TEAM_HEALTHY 107 +#define VARIOUS_TRY_HEAL_QUARTER_HP 108 +#define VARIOUS_REMOVE_TERRAIN 109 +#define VARIOUS_JUMP_IF_OBSTRUCT 110 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 From b6862a41532331a12384fbf56de4921a73334f6f Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 14:01:19 -0400 Subject: [PATCH 075/136] fix jumptocalledmove for assist + attackcanceler --- src/battle_script_commands.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5abc8a9d59..18fd4091b2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6505,6 +6505,7 @@ static void Cmd_jumptocalledmove(void) else gChosenMove = gCurrentMove = gCalledMove; + gBattleStruct->atkCancellerTracker = 0; gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]; } From 806be64935fec921f95eede6c85ddb5ea7ccb863 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 17:10:41 -0400 Subject: [PATCH 076/136] 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 5b090b5e49..0405d5055f 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 7edc4eadce..bdb1b49129 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 077/136] 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 0405d5055f..98056aff2f 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 bdb1b49129..ac9e9dc992 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; From e037cb927652e3e432dce3828d3a3239d1b129a9 Mon Sep 17 00:00:00 2001 From: Ariel Antonitis Date: Mon, 20 Sep 2021 18:28:26 -0400 Subject: [PATCH 078/136] Fixed Nature Power move on different terrains. --- src/battle_script_commands.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 00a52d6c58..e1d51bd05e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11301,7 +11301,7 @@ static void Cmd_setcharge(void) static void Cmd_callterrainattack(void) // nature power { gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); - gCurrentMove = sNaturePowerMoves[gBattleTerrain]; + gCurrentMove = GetNaturePowerMove(); gBattlerTarget = GetMoveTarget(gCurrentMove, 0); BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]); gBattlescriptCurrInstr++; @@ -11309,7 +11309,14 @@ static void Cmd_callterrainattack(void) // nature power u16 GetNaturePowerMove(void) { - //TODO terrain + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return MOVE_MOONBLAST; + else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + return MOVE_THUNDERBOLT; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + return MOVE_ENERGY_BALL; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + return MOVE_PSYCHIC; return sNaturePowerMoves[gBattleTerrain]; } From 32d19a9b19456463fcac5046be0a80ba0dcc35c0 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 20 Sep 2021 21:36:10 -0400 Subject: [PATCH 079/136] syntax fixes. add B_PRANKSTER_DARK_TYPES check to perish song --- data/battle_scripts_1.s | 4 ++-- src/battle_script_commands.c | 8 ++++++-- src/battle_util.c | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 075e9d45ba..a7a8c1aa23 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8153,8 +8153,8 @@ BattleScript_EjectPackActivates:: BattleScript_DarkTypePreventsPrankster:: attackstring ppreduce - pause 0x20 + pause B_WAIT_TIME_SHORT printstring STRINGID_ITDOESNTAFFECT - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT goto BattleScript_MoveEnd diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e63653b453..4413eeec6d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5046,7 +5046,7 @@ static void Cmd_moveend(void) MoveValuesCleanUp(); gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]); - gBattleStruct->atkCancellerTracker = 0; // run all cancellers on next target + gBattleStruct->atkCancellerTracker = 0; // Run all cancellers on next target gBattlescriptCurrInstr = BattleScript_FlushMessageBox; return; } @@ -10730,7 +10730,11 @@ static void Cmd_trysetperishsong(void) { if (gStatuses3[i] & STATUS3_PERISH_SONG || gBattleMons[i].ability == ABILITY_SOUNDPROOF - || (i != gBattlerAttacker && GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(i, TYPE_DARK))) + || (B_PRANKSTER_DARK_TYPES >= GEN_7 + && i != gBattlerAttacker + && GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER + && IS_BATTLER_OF_TYPE(i, TYPE_DARK)) + ) { notAffectedCount++; } diff --git a/src/battle_util.c b/src/battle_util.c index 21efe63a63..00edf07878 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3424,7 +3424,7 @@ u8 AtkCanceller_UnableToUseMove(void) && GetBattlerAbility(gBattlerTarget) != ABILITY_MAGIC_BOUNCE) // Magic bounce will bounce back prankster'd status move instead of blocking it { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) - CancelMultiTurnMoves(gBattlerAttacker); // don't cancel moves that can hit two targets bc one target might not be protected + CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected gBattleScripting.battler = gBattlerAbility = gBattlerTarget; gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; effect = 1; From b38761e6a8561622b1f3424735f63ad2f723488e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 20 Sep 2021 22:26:02 -0400 Subject: [PATCH 080/136] add fairy to dex search --- src/pokedex.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pokedex.c b/src/pokedex.c index cc469b32f8..9de5e0c744 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -1393,6 +1393,7 @@ static const struct SearchOptionText sDexSearchTypeOptions[NUMBER_OF_MON_TYPES + {gText_DexEmptyString, gTypeNames[TYPE_ICE]}, {gText_DexEmptyString, gTypeNames[TYPE_DRAGON]}, {gText_DexEmptyString, gTypeNames[TYPE_DARK]}, + {gText_DexEmptyString, gTypeNames[TYPE_FAIRY]}, {}, }; @@ -1427,6 +1428,7 @@ static const u8 sDexSearchTypeIds[NUMBER_OF_MON_TYPES] = TYPE_ICE, TYPE_DRAGON, TYPE_DARK, + TYPE_FAIRY, }; // Number pairs are the task data for tracking the cursor pos and scroll offset of each option list From 9c79ba05fc1d1c5fdc312425ed1bf5acdcbfe7b8 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 21 Sep 2021 11:38:37 -0400 Subject: [PATCH 081/136] allies do not block prankster --- 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 00edf07878..a7af8232b0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3417,7 +3417,7 @@ u8 AtkCanceller_UnableToUseMove(void) #if B_PRANKSTER_DARK_TYPES >= GEN_7 if (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_MOVE_STATUS(gCurrentMove) - && gBattlerAttacker != gBattlerTarget + && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget) && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_OPPONENTS_FIELD) && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE) From 80a48de70256b9639761d5c295d17fc8bc023f9a Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 21 Sep 2021 11:54:59 -0400 Subject: [PATCH 082/136] ally cannot block prankster + perish song --- data/battle_scripts_1.s | 3 ++- src/battle_script_commands.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a7a8c1aa23..c843fb96b6 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3700,7 +3700,8 @@ BattleScript_EffectPerishSong:: setbyte gBattlerTarget, 0 BattleScript_PerishSongLoop:: jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked - jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_PerishSongLoopIncrement @ cannot block your own perish song + jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_PerishSongLoopIncrement @ Cannot block your own perish song + jumpiftargetally BattleScript_PerishSongLoopIncrement @ Cannot block ally perish song jumpifability BS_ATTACKER, ABILITY_PRANKSTER, BattleScript_PerishSongCheckPrankster goto BattleScript_PerishSongLoopIncrement BattleScript_PerishSongCheckPrankster: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4413eeec6d..5dce3cda2d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10731,7 +10731,7 @@ static void Cmd_trysetperishsong(void) if (gStatuses3[i] & STATUS3_PERISH_SONG || gBattleMons[i].ability == ABILITY_SOUNDPROOF || (B_PRANKSTER_DARK_TYPES >= GEN_7 - && i != gBattlerAttacker + && GetBattlerSide(i) != GetBattlerSide(gBattlerAttacker) && GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(i, TYPE_DARK)) ) From 6eced3f7a439010ce03e600b028d8c11fb7c2929 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 22 Sep 2021 11:53:44 +1200 Subject: [PATCH 083/136] Fix Download Raises user's stat instead of a random target's, and determines stat boosts using the opposing Pokemon's stats. --- src/battle_util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index ccc0c558a8..fdc4277d86 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4045,7 +4045,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move u32 opposingDef = 0, opposingSpDef = 0; opposingBattler = BATTLE_OPPOSITE(battler); - for (i = 0; i < 2; opposingBattler ^= BIT_SIDE, i++) + for (i = 0; i < 2; opposingBattler ^= BIT_FLANK, i++) { if (IsBattlerAlive(opposingBattler)) { @@ -4069,6 +4069,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move { gBattleMons[battler].statStages[statId]++; SET_STATCHANGER(statId, 1, FALSE); + gBattlerAttacker = battler; PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); BattleScriptPushCursorAndCallback(BattleScript_AttackerAbilityStatRaiseEnd3); effect++; From 7571d56140d71869a6959a20dfc0ef7bb5dd1f39 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Tue, 21 Sep 2021 22:57:05 -0300 Subject: [PATCH 084/136] Applied Egg's implementation of telepathy --- src/battle_util.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 591f0bac0a..bbc045e39e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8129,27 +8129,18 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat modifier = UQ_4_12(1.0); } - if (GetBattlerAbility(battlerDef) == ABILITY_WONDER_GUARD && modifier <= UQ_4_12(1.0) && gBattleMoves[move].power) + if (((GetBattlerAbility(battlerDef) == ABILITY_WONDER_GUARD && modifier <= UQ_4_12(1.0)) + || (GetBattlerAbility(battlerDef) == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk))) + && gBattleMoves[move].power) { modifier = UQ_4_12(0.0); if (recordAbilities) { - gLastUsedAbility = ABILITY_WONDER_GUARD; + gLastUsedAbility = gBattleMons[battlerDef].ability; gMoveResultFlags |= MOVE_RESULT_MISSED; gLastLandedMoves[battlerDef] = 0; gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_DMG; - RecordAbilityBattle(battlerDef, ABILITY_WONDER_GUARD); - } - } - if (GetBattlerAbility(battlerDef) == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk)) { - modifier = UQ_4_12(0.0); - if (recordAbilities) - { - gLastUsedAbility = ABILITY_TELEPATHY; - gMoveResultFlags |= MOVE_RESULT_MISSED; - gLastLandedMoves[battlerDef] = 0; - gBattleCommunication[6] = B_MSG_AVOIDED_DMG; - RecordAbilityBattle(battlerDef, ABILITY_TELEPATHY); + RecordAbilityBattle(battlerDef, gBattleMons[battlerDef].ability); } } From b65b27c0dd7dc1e51a80ee5dca14db43288d60a2 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Wed, 22 Sep 2021 00:20:34 -0300 Subject: [PATCH 085/136] Adds missing check for Egg in Illusion --- src/battle_util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_util.c b/src/battle_util.c index 0f18efb9af..fce7c1eeb6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8746,6 +8746,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId) id = i; if (GetMonData(&party[id], MON_DATA_SANITY_HAS_SPECIES) && GetMonData(&party[id], MON_DATA_HP) + && !GetMonData(&party[id], MON_DATA_IS_EGG) && &party[id] != mon && &party[id] != partnerMon) { From 35af7a9cc1b614d12578ff87cea699ee9dd76aa9 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 22 Sep 2021 15:44:13 +1200 Subject: [PATCH 086/136] Fix Foul Play if != else if. Pretty sure I broke this when adding Body Press. --- 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 0f18efb9af..fa38778abb 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7791,7 +7791,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b atkStage = gBattleMons[battlerDef].statStages[STAT_SPATK]; } } - if (gBattleMoves[move].effect == EFFECT_BODY_PRESS) + else if (gBattleMoves[move].effect == EFFECT_BODY_PRESS) { atkStat = gBattleMons[battlerAtk].defense; atkStage = gBattleMons[battlerAtk].statStages[STAT_DEF]; From 0ee13418dc5c8867673fecab6e61c40fc6b78243 Mon Sep 17 00:00:00 2001 From: sbird Date: Wed, 22 Sep 2021 13:15:43 +0200 Subject: [PATCH 087/136] [ai] use expected value move dmg calculation --- include/battle_script_commands.h | 1 + src/battle_ai_util.c | 16 +++++++++++++--- src/battle_script_commands.c | 9 +++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index 2e6a0aa4eb..dec1596f21 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -13,6 +13,7 @@ struct StatFractions }; s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility); +s8 GetInverseCritChance(u8 battlerAtk, u8 battlerDef, u32 move); u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move); u8 GetBattlerTurnOrderNum(u8 battlerId); bool32 NoAliveMonsForEitherParty(void); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 48d3817c8e..b68c68e1bf 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -711,7 +711,8 @@ static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef) s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef) { - s32 dmg, moveType; + s32 dmg, moveType, critDmg, normalDmg; + s8 critChance; SaveBattlerData(battlerAtk); SaveBattlerData(battlerDef); @@ -722,7 +723,15 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef) gBattleStruct->dynamicMoveType = 0; SetTypeBeforeUsingMove(move, battlerAtk); GET_MOVE_TYPE(move, moveType); - dmg = CalculateMoveDamage(move, battlerAtk, battlerDef, moveType, 0, AI_GetIfCrit(move, battlerAtk, battlerDef), FALSE, FALSE); + + critChance = GetInverseCritChance(battlerAtk, battlerDef, move); + normalDmg = CalculateMoveDamage(move, battlerAtk, battlerDef, moveType, 0, FALSE, FALSE, FALSE); + critDmg = CalculateMoveDamage(move, battlerAtk, battlerDef, moveType, 0, TRUE, FALSE, FALSE); + + if(critChance == -1) + dmg = normalDmg; + else + dmg = (critDmg + normalDmg * (critChance - 1)) / critChance; // handle dynamic move damage switch (gBattleMoves[move].effect) @@ -749,7 +758,8 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef) //case EFFECT_METAL_BURST: //case EFFECT_COUNTER: default: - dmg *= (100 - (Random() % 10)) / 100; // add random factor + //do not add the random factor, it's an average case analysis + //dmg *= (100 - (Random() % 10)) / 100; // add random factor break; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e1d51bd05e..a10635e1a8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1822,6 +1822,15 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi return critChance; } +s8 GetInverseCritChance(u8 battlerAtk, u8 battlerDef, u32 move) +{ + s32 critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE); + if(critChanceIndex < 0) + return -1; + else + return sCriticalHitChance[critChanceIndex]; +} + static void Cmd_critcalc(void) { s32 critChance = CalcCritChanceStage(gBattlerAttacker, gBattlerTarget, gCurrentMove, TRUE); From fc84ebbd3eb9333bc4df1b4eb2b98d0d518c6435 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 22 Sep 2021 08:06:42 -0400 Subject: [PATCH 088/136] redo prankster checks to handle assist --- include/battle.h | 1 + src/battle_main.c | 2 ++ src/battle_util.c | 17 +++++++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/battle.h b/include/battle.h index 36646c9fef..103936540d 100644 --- a/include/battle.h +++ b/include/battle.h @@ -146,6 +146,7 @@ struct ProtectStruct u32 custap:1; // also quick claw u32 touchedProtectLike:1; u32 disableEjectPack:1; + u32 pranksterElevated:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; diff --git a/src/battle_main.c b/src/battle_main.c index 74995bbf3a..aec69362bf 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4293,6 +4293,7 @@ s8 GetChosenMovePriority(u32 battlerId) { u16 move; + gProtectStructs[battlerId].pranksterElevated = 0; if (gProtectStructs[battlerId].noValidMoves) move = MOVE_STRUGGLE; else @@ -4314,6 +4315,7 @@ s8 GetMovePriority(u32 battlerId, u16 move) } else if (GetBattlerAbility(battlerId) == ABILITY_PRANKSTER && IS_MOVE_STATUS(move)) { + gProtectStructs[battlerId].pranksterElevated = 1; priority++; } else if (GetBattlerAbility(battlerId) == ABILITY_TRIAGE) diff --git a/src/battle_util.c b/src/battle_util.c index a7af8232b0..f438df057c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3415,13 +3415,14 @@ u8 AtkCanceller_UnableToUseMove(void) break; case CANCELLER_PRANKSTER: #if B_PRANKSTER_DARK_TYPES >= GEN_7 - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER - && IS_MOVE_STATUS(gCurrentMove) + if (gProtectStructs[gBattlerAttacker].pranksterElevated && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget) - && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_OPPONENTS_FIELD) - && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) + && !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves + && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) // Only Dark types can block Prankster'e && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE) - && GetBattlerAbility(gBattlerTarget) != ABILITY_MAGIC_BOUNCE) // Magic bounce will bounce back prankster'd status move instead of blocking it + && !(IS_MOVE_STATUS(gCurrentMove) // Magic bounce/coat will bounce back prankster'd status move instead of blocking it + && (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE || TestMoveFlags(gCurrentMove, FLAG_MAGIC_COAT_AFFECTED))) + ) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected @@ -6853,7 +6854,11 @@ u8 GetMoveTarget(u16 move, u8 setTarget) moveTarget = setTarget - 1; else moveTarget = gBattleMoves[move].target; - + + // Special cases + if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) + moveTarget = MOVE_TARGET_USER; + switch (moveTarget) { case MOVE_TARGET_SELECTED: From 53d985eeddafe743711e2b92c6be514ce95df768 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Wed, 22 Sep 2021 10:29:32 -0300 Subject: [PATCH 089/136] Scald thaw flag config for = GEN_6 + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_THAW_USER, + #else + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST, + #endif .effect = EFFECT_SCALD, .power = 80, .type = TYPE_WATER, @@ -7943,7 +7948,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, - .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_THAW_USER, .split = SPLIT_SPECIAL, }, From 13062b5a8fad46ec1d4e9ecfcdee08b15f334023 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 22 Sep 2021 09:43:40 -0400 Subject: [PATCH 090/136] fix lash out, obstruct, and decorate --- asm/macros/battle_script.inc | 5 --- data/battle_scripts_1.s | 39 +++++++++------------- include/battle.h | 1 - include/constants/battle_script_commands.h | 1 - src/battle_main.c | 1 - src/battle_script_commands.c | 27 ++++++--------- src/battle_util.c | 2 +- 7 files changed, 26 insertions(+), 50 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 70ddbdf58c..02c2a91d13 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1816,11 +1816,6 @@ various BS_ATTACKER, VARIOUS_REMOVE_TERRAIN .endm - .macro jumpifobstruct ptr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_OBSTRUCT - .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 261145048a..755b2c382f 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -382,6 +382,7 @@ gBattleScriptsForMoveEffects:: BattleScript_EffectDecorate: attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost @@ -396,13 +397,13 @@ BattleScript_DecorateBoost: statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_DecorateBoostSpAtk jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_DecorateBoostSpAtk printfromtable gStatUpStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG BattleScript_DecorateBoostSpAtk: setstatchanger STAT_SPATK, 2, FALSE statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd printfromtable gStatUpStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectRemoveTerrain: @@ -421,13 +422,13 @@ BattleScript_EffectRemoveTerrain: healthbarupdate BS_TARGET datahpupdate BS_TARGET critmessage - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG resultmessage - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG removeterrain jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_MoveEnd printfromtable gTerrainEndingStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG, NULL tryfaintmon BS_TARGET, FALSE, NULL goto BattleScript_MoveEnd @@ -441,8 +442,8 @@ BattleScript_EffectCoaching: setallytonexttarget EffectCoaching_CheckAllyStats goto BattleScript_ButItFailed EffectCoaching_CheckAllyStats: - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_CoachingWorks - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 12, BattleScript_CoachingWorks + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_CoachingWorks + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, MAX_STAT_STAGE, BattleScript_CoachingWorks goto BattleScript_ButItFailed @ ally at max atk, def BattleScript_CoachingWorks: attackanimation @@ -453,13 +454,13 @@ BattleScript_CoachingWorks: statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_CoachingBoostDef jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_CoachingBoostDef printfromtable gStatUpStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG BattleScript_CoachingBoostDef: setstatchanger STAT_DEF, 1, FALSE statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd printfromtable gStatUpStringIds - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectJungleHealing: @@ -478,7 +479,7 @@ JungleHealing_RestoreTargetHealth: healthbarupdate BS_TARGET datahpupdate BS_TARGET printstring STRINGID_PKMNREGAINEDHEALTH - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG BattleScript_JungleHealing_TryCureStatus: jumpifmove MOVE_LIFE_DEW, BattleScript_JungleHealingTryRestoreAlly @ life dew only heals jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_JungleHealingCureStatus @@ -487,7 +488,7 @@ BattleScript_JungleHealingCureStatus: curestatus BS_TARGET updatestatusicon BS_TARGET printstring STRINGID_PKMNSTATUSNORMAL - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG BattleScript_JungleHealingTryRestoreAlly: jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd addbyte gBattleCommunication, 1 @@ -2233,17 +2234,6 @@ BattleScript_MoveMissed:: effectivenesssound resultmessage waitmessage B_WAIT_TIME_LONG - jumpifobstruct BattleScript_ObstructActivates - goto BattleScript_MoveEnd - -BattleScript_ObstructActivates: - jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_DEF, MIN_STAT_STAGE, BattleScript_ObstructActivationEnd - setgraphicalstatchangevalues - playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 - statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_ObstructActivationEnd - printfromtable gStatDownStringIds - waitmessage B_WAIT_TIME_LONG -BattleScript_ObstructActivationEnd: goto BattleScript_MoveEnd BattleScript_EffectSleep:: @@ -3624,12 +3614,13 @@ BattleScript_EffectEerieSpell:: healthbarupdate BS_TARGET datahpupdate BS_TARGET critmessage - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG resultmessage - waitmessage 0x40 + waitmessage B_WAIT_TIME_LONG tryfaintmon BS_TARGET, FALSE, NULL eeriespellppreduce BattleScript_MoveEnd printstring STRINGID_PKMNREDUCEDPP + waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectSpite:: diff --git a/include/battle.h b/include/battle.h index 491e67acf7..cf231f5ae6 100644 --- a/include/battle.h +++ b/include/battle.h @@ -143,7 +143,6 @@ struct ProtectStruct u32 usedGravityPreventedMove:1; u32 powderSelfDmg:1; u32 usedThroatChopPreventedMove:1; - u32 statFell:1; u32 statRaised:1; u32 micle:1; u32 custap:1; // also quick claw diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 1f3a72a672..12a789c8b8 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -183,7 +183,6 @@ #define VARIOUS_JUMP_IF_TEAM_HEALTHY 111 #define VARIOUS_TRY_HEAL_QUARTER_HP 112 #define VARIOUS_REMOVE_TERRAIN 113 -#define VARIOUS_JUMP_IF_OBSTRUCT 114 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_main.c b/src/battle_main.c index ebdd54e415..0780c88021 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3093,7 +3093,6 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].usesBouncedMove = 0; gProtectStructs[gActiveBattler].usedGravityPreventedMove = 0; gProtectStructs[gActiveBattler].usedThroatChopPreventedMove = 0; - gProtectStructs[gActiveBattler].statFell = 0; gProtectStructs[gActiveBattler].statRaised = 0; gDisableStructs[gActiveBattler].isFirstTurn = 2; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e58e347258..313d3ea460 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1237,16 +1237,21 @@ static const u8 sBattlePalaceNatureToFlavorTextId[NUM_NATURES] = bool32 IsBattlerProtected(u8 battlerId, u16 move) { + // Decorate bypasses protect and detect, but not crafty shield + if (move == MOVE_DECORATE) + { + if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD) + return TRUE; + else if (gProtectStructs[battlerId].protected) + return FALSE; + } + if (!(gBattleMoves[move].flags & FLAG_PROTECT_AFFECTED)) return FALSE; else if (gBattleMoves[move].effect == MOVE_EFFECT_FEINT) return FALSE; else if (gProtectStructs[battlerId].protected) - { - if (move == MOVE_DECORATE && !(gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD)) - return FALSE; // decorate bypasses protect and detect, but not crafty shield return TRUE; - } else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD && gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; @@ -4778,6 +4783,7 @@ static void Cmd_moveend(void) } else if (gProtectStructs[gBattlerTarget].obstructed && gCurrentMove != MOVE_SUCKER_PUNCH) { + gProtectStructs[gBattlerAttacker].touchedProtectLike = 0; i = gBattlerAttacker; gBattlerAttacker = gBattlerTarget; gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable @@ -8697,19 +8703,6 @@ static void Cmd_various(void) } gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain break; - case VARIOUS_JUMP_IF_OBSTRUCT: - // if obstruct blocked a contact move, sharply lower defense - if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker) && gProtectStructs[gBattlerTarget].obstructed && !IS_MOVE_STATUS(gCurrentMove)) - { - SET_STATCHANGER(STAT_DEF, 2, TRUE); - gBattleScripting.battler = gBattlerAttacker; - gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); - } - else - { - gBattlescriptCurrInstr += 7; - } - return; } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index 0473fa054e..16adcda754 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7468,7 +7468,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; break; case EFFECT_LASH_OUT: - if (gProtectStructs[battlerAtk].statFell == 1) + if (gSpecialStatuses[battlerAtk].statFell == 1) basePower *= 2; break; case EFFECT_EXPLOSION: From 707d49242e8f733f5bc797b219364cdc9d73b394 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Wed, 22 Sep 2021 12:31:23 -0300 Subject: [PATCH 091/136] Revert "Scald thaw flag config for Gen 5" --- src/data/battle_moves.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 0fc3b3e429..657341b5ef 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -7935,11 +7935,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SCALD] = { - #if B_UPDATED_MOVE_DATA >= GEN_6 - .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_THAW_USER, - #else - .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST, - #endif .effect = EFFECT_SCALD, .power = 80, .type = TYPE_WATER, @@ -7948,6 +7943,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_THAW_USER, .split = SPLIT_SPECIAL, }, From 303e31ae251b289fc46774314140617228d9e44e Mon Sep 17 00:00:00 2001 From: sbird Date: Wed, 22 Sep 2021 18:05:58 +0200 Subject: [PATCH 092/136] [ai] use expected value to simulate EFFECT_PSYWAVE --- src/battle_ai_util.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b68c68e1bf..95d979e943 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -737,6 +737,8 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef) switch (gBattleMoves[move].effect) { case EFFECT_LEVEL_DAMAGE: + case EFFECT_PSYWAVE: + //psywave's expected damage is equal to the user's level dmg = gBattleMons[battlerAtk].level; break; case EFFECT_DRAGON_RAGE: @@ -745,16 +747,6 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef) case EFFECT_SONICBOOM: dmg = 20; break; - case EFFECT_PSYWAVE: - { - u32 randDamage; - if (B_PSYWAVE_DMG >= GEN_6) - randDamage = (Random() % 101); - else - randDamage = (Random() % 11) * 10; - dmg = gBattleMons[battlerAtk].level * (randDamage + 50) / 100; - } - break; //case EFFECT_METAL_BURST: //case EFFECT_COUNTER: default: From 3559a1b8e6364f638995311451230a0648a85e80 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 22 Sep 2021 16:09:23 -0400 Subject: [PATCH 093/136] fix prankster + magic coat --- data/battle_scripts_1.s | 11 +++++++++++ include/battle_scripts.h | 1 + include/battle_util.h | 1 + src/battle_script_commands.c | 13 +++++++++++-- src/battle_util.c | 22 ++++++++++++++-------- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c843fb96b6..f949278fb4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6169,6 +6169,17 @@ BattleScript_MagicCoatBounce:: setmagiccoattarget BS_ATTACKER return +BattleScript_MagicCoatBouncePrankster:: + attackstring + ppreduce + pause B_WAIT_TIME_SHORT + printfromtable gMagicCoatBounceStringIds + waitmessage B_WAIT_TIME_LONG + printstring STRINGID_ITDOESNTAFFECT + waitmessage B_WAIT_TIME_LONG + orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT + goto BattleScript_MoveEnd + BattleScript_SnatchedMove:: attackstring ppreduce diff --git a/include/battle_scripts.h b/include/battle_scripts.h index c7b8cb0916..e215d984e5 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -97,6 +97,7 @@ extern const u8 BattleScript_SelectingImprisonedMove[]; extern const u8 BattleScript_SelectingImprisonedMoveInPalace[]; extern const u8 BattleScript_GrudgeTakesPp[]; extern const u8 BattleScript_MagicCoatBounce[]; +extern const u8 BattleScript_MagicCoatBouncePrankster[]; extern const u8 BattleScript_SnatchedMove[]; extern const u8 BattleScript_EnduredMsg[]; extern const u8 BattleScript_OneHitKOMsg[]; diff --git a/include/battle_util.h b/include/battle_util.h index 4dac63111a..9186a8b82d 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -151,6 +151,7 @@ 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); +bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5dce3cda2d..2df5abcdad 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1405,8 +1405,17 @@ static void Cmd_attackcanceler(void) gProtectStructs[gBattlerTarget].bounceMove = 0; gProtectStructs[gBattlerTarget].usesBouncedMove = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 0; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MagicCoatBounce; + if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker)) + { + // Opponent used a prankster'ed magic coat -> reflected status move should fail against a dark type attacker + gBattlerTarget = gBattlerAttacker; + gBattlescriptCurrInstr = BattleScript_MagicCoatBouncePrankster; + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MagicCoatBounce; + } return; } else if (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE diff --git a/src/battle_util.c b/src/battle_util.c index f438df057c..24ae917352 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3415,14 +3415,8 @@ u8 AtkCanceller_UnableToUseMove(void) break; case CANCELLER_PRANKSTER: #if B_PRANKSTER_DARK_TYPES >= GEN_7 - if (gProtectStructs[gBattlerAttacker].pranksterElevated - && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget) - && !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves - && IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_DARK) // Only Dark types can block Prankster'e - && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE) - && !(IS_MOVE_STATUS(gCurrentMove) // Magic bounce/coat will bounce back prankster'd status move instead of blocking it - && (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE || TestMoveFlags(gCurrentMove, FLAG_MAGIC_COAT_AFFECTED))) - ) + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget) + && !(IS_MOVE_STATUS(gCurrentMove) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE)) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected @@ -9195,3 +9189,15 @@ bool32 TryRoomService(u8 battlerId) return FALSE; } } + +bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef) +{ + if (gProtectStructs[battlerPrankster].pranksterElevated + && GetBattlerSide(battlerPrankster) != GetBattlerSide(battlerDef) + && !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves + && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) // Only Dark types can block Prankster'ed + && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + return TRUE; + else + return FALSE; +} From 9bf2ffe45902a8ba23a0310a847e0cb32986bb74 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 22 Sep 2021 21:15:02 -0400 Subject: [PATCH 094/136] fix lash out stat fell --- include/battle.h | 2 +- src/battle_script_commands.c | 6 +++--- src/battle_util.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/battle.h b/include/battle.h index cf231f5ae6..b36780ee5f 100644 --- a/include/battle.h +++ b/include/battle.h @@ -148,6 +148,7 @@ struct ProtectStruct u32 custap:1; // also quick claw u32 touchedProtectLike:1; u32 disableEjectPack:1; + u32 statFell:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; @@ -156,7 +157,6 @@ struct ProtectStruct struct SpecialStatus { - u8 statFell:1; u8 statLowered:1; u8 lightningRodRedirected:1; u8 restoredBattlerSprite: 1; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ea9278f45f..42e723ecc3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5164,12 +5164,12 @@ static void Cmd_moveend(void) { u8 battler = battlers[i]; if (IsBattlerAlive(battler) - && gSpecialStatuses[battler].statFell + && gProtectStructs[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; + gProtectStructs[battler].statFell = FALSE; gActiveBattler = gBattleScripting.battler = battler; gLastUsedItem = gBattleMons[battler].item; BattleScriptPushCursor(); @@ -9409,7 +9409,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { // 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; + gProtectStructs[gActiveBattler].statFell = 1; 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 6eb6556363..80b5f824cd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5996,10 +5996,10 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } break; case HOLD_EFFECT_EJECT_PACK: - if (gSpecialStatuses[battlerId].statFell + if (gProtectStructs[battlerId].statFell && !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out { - gSpecialStatuses[battlerId].statFell = FALSE; + gProtectStructs[battlerId].statFell = FALSE; gActiveBattler = gBattleScripting.battler = battlerId; effect = ITEM_STATS_CHANGE; if (moveTurn) @@ -7468,7 +7468,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; break; case EFFECT_LASH_OUT: - if (gSpecialStatuses[battlerAtk].statFell == 1) + if (gProtectStructs[battlerAtk].statFell) basePower *= 2; break; case EFFECT_EXPLOSION: From 936f2c7bcbe0fc67bcac40c0e7e805e1bb784f1d Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 22 Sep 2021 21:51:37 -0400 Subject: [PATCH 095/136] fix eject pack weak armor special case --- src/battle_main.c | 1 + src/battle_script_commands.c | 5 ++--- src/battle_util.c | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index e7139e0d14..4fa6568562 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3094,6 +3094,7 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].usedGravityPreventedMove = 0; gProtectStructs[gActiveBattler].usedThroatChopPreventedMove = 0; gProtectStructs[gActiveBattler].statRaised = 0; + gProtectStructs[gActiveBattler].statFell = 0; gDisableStructs[gActiveBattler].isFirstTurn = 2; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 42e723ecc3..a1e0d7e5f6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5165,6 +5165,7 @@ static void Cmd_moveend(void) u8 battler = battlers[i]; if (IsBattlerAlive(battler) && gProtectStructs[battler].statFell + && gProtectStructs[battler].disableEjectPack == 0 && 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 @@ -9407,9 +9408,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr } else { - // 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) - gProtectStructs[gActiveBattler].statFell = 1; + gProtectStructs[gActiveBattler].statFell = 1; // Eject pack, lash out 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 80b5f824cd..b9f29ae2d6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5997,6 +5997,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) break; case HOLD_EFFECT_EJECT_PACK: if (gProtectStructs[battlerId].statFell + && gProtectStructs[battlerId].disableEjectPack == 0 && !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out { gProtectStructs[battlerId].statFell = FALSE; From d4a153bf14f76165dc36646625ccd918ce88d648 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 23 Sep 2021 12:21:16 -0600 Subject: [PATCH 096/136] Update data/battle_scripts_1.s Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- 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 2b290c673f..ece6e73dc5 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3701,7 +3701,7 @@ BattleScript_EffectPerishSong:: BattleScript_PerishSongLoop:: jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_PerishSongLoopIncrement @ Cannot block your own perish song - jumpiftargetally BattleScript_PerishSongLoopIncrement @ Cannot block ally perish song + jumpiftargetally BattleScript_PerishSongLoopIncrement @ Cannot block ally perish song jumpifability BS_ATTACKER, ABILITY_PRANKSTER, BattleScript_PerishSongCheckPrankster goto BattleScript_PerishSongLoopIncrement BattleScript_PerishSongCheckPrankster: From 2cea541b2afb47d7cfed84cf3c173fa994ee5670 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 23 Sep 2021 12:21:26 -0600 Subject: [PATCH 097/136] Update src/battle_script_commands.c Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b5c690dc23..cb0dfd23e2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1407,7 +1407,7 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MULTISTRING_CHOOSER] = 0; if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker)) { - // Opponent used a prankster'ed magic coat -> reflected status move should fail against a dark type attacker + // Opponent used a prankster'd magic coat -> reflected status move should fail against a dark-type attacker gBattlerTarget = gBattlerAttacker; gBattlescriptCurrInstr = BattleScript_MagicCoatBouncePrankster; } From 8a9d28d97f796498ca2ad49776c3663fa711c860 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 23 Sep 2021 12:21:36 -0600 Subject: [PATCH 098/136] 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 574a11b4c4..0854cb6e03 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9239,7 +9239,7 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef) if (gProtectStructs[battlerPrankster].pranksterElevated && GetBattlerSide(battlerPrankster) != GetBattlerSide(battlerDef) && !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves - && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) // Only Dark types can block Prankster'ed + && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) // Only Dark-types can block Prankster'd && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) return TRUE; else From 94ec25319f2d51c6ab3f1211f9aba51f624c2359 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 23 Sep 2021 14:35:37 -0400 Subject: [PATCH 099/136] syntax fixes. Use BlocksPrankster for perish song battle script --- asm/macros/battle_script.inc | 5 +++++ data/battle_scripts_1.s | 7 +------ include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 12 +++++++----- src/battle_util.c | 22 +++++++++++----------- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 7ca6bfa6dc..6189c855d0 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1796,6 +1796,11 @@ .4byte \terrainFlags .4byte \ptr .endm + + .macro jumpifpranksterblocked battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED + .4byte \ptr + .endm @ helpful macros .macro setstatchanger stat:req, stages:req, down:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ece6e73dc5..e5d4466c4d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3700,12 +3700,7 @@ BattleScript_EffectPerishSong:: setbyte gBattlerTarget, 0 BattleScript_PerishSongLoop:: jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked - jumpifbyteequal gBattlerAttacker, gBattlerTarget, BattleScript_PerishSongLoopIncrement @ Cannot block your own perish song - jumpiftargetally BattleScript_PerishSongLoopIncrement @ Cannot block ally perish song - jumpifability BS_ATTACKER, ABILITY_PRANKSTER, BattleScript_PerishSongCheckPrankster - goto BattleScript_PerishSongLoopIncrement -BattleScript_PerishSongCheckPrankster: - jumpiftype BS_TARGET, TYPE_DARK, BattleScript_PerishSongNotAffected + jumpifpranksterblocked BS_TARGET, BattleScript_PerishSongNotAffected BattleScript_PerishSongLoopIncrement:: addbyte gBattlerTarget, 1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_PerishSongLoop diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 66f5925034..e564f54794 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -179,6 +179,7 @@ #define VARIOUS_MAKE_INVISIBLE 107 #define VARIOUS_ROOM_SERVICE 108 #define VARIOUS_JUMP_IF_TERRAIN_AFFECTED 109 +#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 110 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index cb0dfd23e2..4d12ae8fea 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8604,6 +8604,12 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 11; } return; + case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED: + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gActiveBattler)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; + return; } gBattlescriptCurrInstr += 3; @@ -10757,11 +10763,7 @@ static void Cmd_trysetperishsong(void) { if (gStatuses3[i] & STATUS3_PERISH_SONG || gBattleMons[i].ability == ABILITY_SOUNDPROOF - || (B_PRANKSTER_DARK_TYPES >= GEN_7 - && GetBattlerSide(i) != GetBattlerSide(gBattlerAttacker) - && GetBattlerAbility(gBattlerAttacker) == ABILITY_PRANKSTER - && IS_BATTLER_OF_TYPE(i, TYPE_DARK)) - ) + || BlocksPrankster(gCurrentMove, gBattlerAttacker, i)) { notAffectedCount++; } diff --git a/src/battle_util.c b/src/battle_util.c index 0854cb6e03..8655d47d87 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3414,17 +3414,15 @@ u8 AtkCanceller_UnableToUseMove(void) gBattleStruct->atkCancellerTracker++; break; case CANCELLER_PRANKSTER: - #if B_PRANKSTER_DARK_TYPES >= GEN_7 - if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget) - && !(IS_MOVE_STATUS(gCurrentMove) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE)) - { - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) - CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected - gBattleScripting.battler = gBattlerAbility = gBattlerTarget; - gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; - effect = 1; - } - #endif + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget) + && !(IS_MOVE_STATUS(gCurrentMove) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE)) + { + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) + CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected + gBattleScripting.battler = gBattlerAbility = gBattlerTarget; + gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; + effect = 1; + } gBattleStruct->atkCancellerTracker++; break; case CANCELLER_END: @@ -9236,6 +9234,7 @@ void DoBurmyFormChange(u32 monId) bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef) { + #if B_PRANKSTER_DARK_TYPES >= GEN_7 if (gProtectStructs[battlerPrankster].pranksterElevated && GetBattlerSide(battlerPrankster) != GetBattlerSide(battlerDef) && !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves @@ -9243,5 +9242,6 @@ bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef) && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) return TRUE; else + #endif return FALSE; } From 767e25bfed68ff1939c1074d34f5f7d03da2592a Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 23 Sep 2021 13:19:12 -0600 Subject: [PATCH 100/136] Update asm/macros/battle_script.inc Co-authored-by: ultima-soul <33333039+ultima-soul@users.noreply.github.com> --- asm/macros/battle_script.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index b2e8bf343e..d1a0fb63f1 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1796,7 +1796,6 @@ .4byte \terrainFlags .4byte \ptr .endm - .macro jumpifpranksterblocked battler:req, ptr:req various \battler, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED .4byte \ptr From fe6a11e5ec9210be4a183cb10b7bac8424a3bc32 Mon Sep 17 00:00:00 2001 From: ultima-soul <33333039+ultima-soul@users.noreply.github.com> Date: Thu, 23 Sep 2021 12:26:36 -0700 Subject: [PATCH 101/136] Update asm/macros/battle_script.inc --- asm/macros/battle_script.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index d1a0fb63f1..12cf20a9c0 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1796,6 +1796,7 @@ .4byte \terrainFlags .4byte \ptr .endm + .macro jumpifpranksterblocked battler:req, ptr:req various \battler, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED .4byte \ptr From 8a2921ef718b5086ed29a11c2570d43a47795afa Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 24 Sep 2021 06:34:25 -0300 Subject: [PATCH 102/136] Completed Black Sludge's effect --- src/battle_util.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index e6137b0f28..e669bfa037 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6120,7 +6120,20 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) break; case HOLD_EFFECT_BLACK_SLUDGE: if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON)) + { goto LEFTOVERS; + } + else if (GetBattlerAbility(battlerId) != ABILITY_MAGIC_GUARD && !moveTurn) + { + gBattleMoveDamage = gBattleMons[battlerId].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_ItemHurtEnd2); + effect = ITEM_HP_CHANGE; + RecordItemEffectBattle(battlerId, battlerHoldEffect); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); + } + break; case HOLD_EFFECT_LEFTOVERS: LEFTOVERS: if (gBattleMons[battlerId].hp < gBattleMons[battlerId].maxHP && !moveTurn) From 4c05520bf3570997e52a6b2619401ffc154995fd Mon Sep 17 00:00:00 2001 From: Syreldar Date: Fri, 24 Sep 2021 16:02:26 +0200 Subject: [PATCH 103/136] Fixed Retaliate's naming. --- data/battle_anim_scripts.s | 4 ++-- data/battle_scripts_1.s | 2 +- include/constants/battle_move_effects.h | 2 +- src/battle_util.c | 2 +- src/data/battle_moves.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index d274717dca..32f089102b 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -532,7 +532,7 @@ gBattleAnims_Moves:: .4byte Move_QUASH .4byte Move_ACROBATICS .4byte Move_REFLECT_TYPE - .4byte Move_RETALITATE + .4byte Move_RETALIATE .4byte Move_FINAL_GAMBIT .4byte Move_BESTOW .4byte Move_INFERNO @@ -5610,7 +5610,7 @@ Move_REFLECT_TYPE: blendoff end -Move_RETALITATE: +Move_RETALIATE: loadspritegfx ANIM_TAG_CUT @Cut monbg ANIM_DEF_PARTNER setalpha 9, 8 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a272f6753e..c5c013db1c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -252,7 +252,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHit @ EFFECT_ROUND .4byte BattleScript_EffectHit @ EFFECT_BRINE .4byte BattleScript_EffectHit @ EFFECT_VENOSHOCK - .4byte BattleScript_EffectHit @ EFFECT_RETALITATE + .4byte BattleScript_EffectHit @ EFFECT_RETALIATE .4byte BattleScript_EffectBulldoze @ EFFECT_BULLDOZE .4byte BattleScript_EffectHit @ EFFECT_FOUL_PLAY .4byte BattleScript_EffectHit @ EFFECT_PSYSHOCK diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 760ee66fd2..440e6e76b6 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -236,7 +236,7 @@ #define EFFECT_ROUND 230 #define EFFECT_BRINE 231 #define EFFECT_VENOSHOCK 232 -#define EFFECT_RETALITATE 233 +#define EFFECT_RETALIATE 233 #define EFFECT_BULLDOZE 234 #define EFFECT_FOUL_PLAY 235 #define EFFECT_PSYSHOCK 236 diff --git a/src/battle_util.c b/src/battle_util.c index e669bfa037..ee1bfe551d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7778,7 +7778,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) MulModifier(&modifier, UQ_4_12(2.0)); break; - case EFFECT_RETALITATE: + case EFFECT_RETALIATE: // todo break; case EFFECT_SOLARBEAM: diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 097f9e07db..a7a2752e00 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -8097,7 +8097,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_RETALIATE] = { - .effect = EFFECT_RETALITATE, + .effect = EFFECT_RETALIATE, .power = 70, .type = TYPE_NORMAL, .accuracy = 100, From 872d2a700858081148dfab5e92a02cbef36f87fd Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Sat, 25 Sep 2021 22:30:45 -0300 Subject: [PATCH 104/136] Made this build again --- 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 e875e01e7f..cf3204727f 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6032,7 +6032,7 @@ BattleScript_GulpMissileGulping:: setgraphicalstatchangevalues playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 waitanimation - printstring STRINGID_PKMNSSTATCHANGED + printstring STRINGID_ATTACKERSSTATROSE waitmessage 0x40 return From a49ea33dd063618a6d6375ef945ed5019e63704c Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Sun, 26 Sep 2021 19:59:56 -0300 Subject: [PATCH 105/136] A lot of fixes -Fixed Gulp Missile's activation. Its effects were happening even if the conditions weren't actually met in battle. -Fixed Gulp Missile activating if the only/last target has already fainted. -Fixed Gulp Missile's Gorging animation, though it still uses Tackle's. -Fixed Gulp Missile's Gorging attack affecting an opponent with Magic Guard. -Fixed Gulp Missile changing Cramorant's form if Surf failed. --- data/battle_anim_scripts.s | 10 ++++----- data/battle_scripts_1.s | 10 +++++++++ src/battle_util.c | 43 +++++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 71dcf8b2be..d7de920967 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -24398,18 +24398,16 @@ General_TotemFlare:: clearmonbg ANIM_ATTACKER end -General_GulpMissile: @ Modified Tackle anim (placeholder) +General_GulpMissile: @ Tackle anim (placeholder) loadspritegfx ANIM_TAG_IMPACT monbg ANIM_ATTACKER setalpha 12, 8 - createsprite gHorizontalLungeSpriteTemplate, ANIM_TARGET, 2, 4, 4 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 4 delay 6 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, ANIM_ATTACKER, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_ATTACKER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 3, 0, 6, 1 - playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_ATTACKER + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET waitforvisualfinish - delay 10 - playse SE_EFFECTIVE clearmonbg ANIM_ATTACKER blendoff end diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index cf3204727f..381c67a30d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6005,9 +6005,14 @@ BattleScript_GulpMissileGorging:: playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE, NULL waitanimation orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000 + effectivenesssound + hitanimation BS_ATTACKER + waitstate + jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_GulpMissileNoDmgGorging healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER, FALSE, NULL +BattleScript_GulpMissileNoDmgGorging: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL waitanimation @@ -6022,9 +6027,14 @@ BattleScript_GulpMissileGulping:: playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE, NULL waitanimation orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000 + effectivenesssound + hitanimation BS_ATTACKER + waitstate + jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_GulpMissileNoDmgGulping healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER, FALSE, NULL +BattleScript_GulpMissileNoDmgGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL waitanimation diff --git a/src/battle_util.c b/src/battle_util.c index ac4257fe71..436ac4d1a6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4985,17 +4985,22 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_GULP_MISSILE: + gBattlerAttacker = battler; + gBattlerTarget = BATTLE_OPPOSITE(battler); if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && IsBattlerAlive(battler) - && gBattleMons[battler].species == SPECIES_CRAMORANT_GORGING) + && IsBattlerAlive(gBattlerAttacker) + && gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; - gBattleMons[battler].species = SPECIES_CRAMORANT; - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; + gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; effect++; @@ -5003,14 +5008,17 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move else if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && IsBattlerAlive(battler) - && gBattleMons[battler].species == SPECIES_CRAMORANT_GULPING) + && IsBattlerAlive(gBattlerAttacker) + && gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; - gBattleMons[battler].species = SPECIES_CRAMORANT; - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; + gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } SET_STATCHANGER(STAT_DEF, 1, TRUE); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; @@ -5054,9 +5062,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_GULP_MISSILE: - if ((effect = ShouldChangeFormHpBased(battler)) - && (gCurrentMove == MOVE_SURF - || gStatuses3[battler] & STATUS3_UNDERWATER)) + if ((effect = ShouldChangeFormHpBased(gBattlerAttacker)) + && (gCurrentMove == MOVE_SURF || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + && TARGET_TURN_DAMAGED + && IsBattlerAlive(gBattlerAttacker)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerFormChange; From ceffaa4e7635c82713d96676263eb3c22a4f0887 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 27 Sep 2021 19:53:42 -0300 Subject: [PATCH 106/136] Another condition fix I accidentally broke Gulp Missile's interaction with the user's Dive, lol. --- src/battle_util.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 436ac4d1a6..556d98e46d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5063,9 +5063,8 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move break; case ABILITY_GULP_MISSILE: if ((effect = ShouldChangeFormHpBased(gBattlerAttacker)) - && (gCurrentMove == MOVE_SURF || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) - && TARGET_TURN_DAMAGED - && IsBattlerAlive(gBattlerAttacker)) + && ((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + && IsBattlerAlive(gBattlerTarget)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerFormChange; From e783cde3873916206b89297b51a72033f22d438f Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 27 Sep 2021 21:31:42 -0300 Subject: [PATCH 107/136] Another small condition fix and small optimization -Checking for IsBattlerAlive is incorrect because Gulp Missile's counterattack should happen even if Cramorant faints. -Made the code a bit more readable. --- src/battle_util.c | 57 +++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 556d98e46d..6b65c72c6e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4985,44 +4985,39 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_GULP_MISSILE: - gBattlerAttacker = battler; - gBattlerTarget = BATTLE_OPPOSITE(battler); if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED - && IsBattlerAlive(gBattlerAttacker) - && gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) + && TARGET_TURN_DAMAGED) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; - gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) { - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; + gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; + effect++; } - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; - effect++; - } - else if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED - && IsBattlerAlive(gBattlerAttacker) - && gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) - { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; - gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) { - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; + gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + SET_STATCHANGER(STAT_DEF, 1, TRUE); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; + effect++; } - SET_STATCHANGER(STAT_DEF, 1, TRUE); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; - effect++; } break; } From 0389dbf9f239025b27f9250f113c9acfa742dc0a Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 29 Sep 2021 06:13:56 -0300 Subject: [PATCH 108/136] More fixes -Removed IsBattlerAlive check for case ABILITY_GULP_MISSILE in ABILITYEFFECT_MOVE_END_ATTACKER. Turns out Cramorant can change form even on single wild battles. -Added a check for IsBattlerAlive in the case ABILITY_GULP_MISSILE of ABILITYEFFECT_MOVE_END, because otherwise, for whatever reason, the user was trying to trigger the Gulping effect even in its base form. -Set the stat to change for the Gulping effect from within the battle script. The rest of the effect is handled there, so may as well. -Fixed the check for case ABILITY_GULP_MISSILE in ABILITYEFFECT_MOVE_END_ATTACKER. Apparently, a silent species change was happening because of the order of the checks. Thanks to AsparagusEduardo for pointing this one out. -Fixed the secondary effect of a target's Gulp Missile affecting an attacker that has fainted. -Fixed the Defense reduction of the Gulping effect bypassing Clear Body. --- data/battle_scripts_1.s | 15 +++++++++++++++ src/battle_util.c | 9 ++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 381c67a30d..0743d21c12 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6012,6 +6012,7 @@ BattleScript_GulpMissileGorging:: healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER, FALSE, NULL + jumpifbyteequal gBattlerFainted, gBattlerAttacker, BattleScript_GulpMissileNoSecondEffectGorging BattleScript_GulpMissileNoDmgGorging: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL @@ -6021,6 +6022,11 @@ BattleScript_GulpMissileNoDmgGorging: seteffectprimary swapattackerwithtarget return +BattleScript_GulpMissileNoSecondEffectGorging: + handleformchange BS_TARGET, 0 + playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL + waitanimation + return BattleScript_GulpMissileGulping:: call BattleScript_AbilityPopUp @@ -6034,10 +6040,13 @@ BattleScript_GulpMissileGulping:: healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER, FALSE, NULL + jumpifbyteequal gBattlerFainted, gBattlerAttacker, BattleScript_GulpMissileNoSecondEffectGulping + jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileGulpingRet BattleScript_GulpMissileNoDmgGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL waitanimation + setstatchanger STAT_DEF, 1, TRUE statbuffchange STAT_BUFF_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, NULL setgraphicalstatchangevalues playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 @@ -6045,6 +6054,12 @@ BattleScript_GulpMissileNoDmgGulping: printstring STRINGID_ATTACKERSSTATROSE waitmessage 0x40 return +BattleScript_GulpMissileNoSecondEffectGulping: + handleformchange BS_TARGET, 0 + playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL + waitanimation +BattleScript_GulpMissileGulpingRet: + return BattleScript_PerishSongCountGoesDown:: printstring STRINGID_PKMNPERISHCOUNTFELL diff --git a/src/battle_util.c b/src/battle_util.c index 6b65c72c6e..20e5d91d1a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4987,7 +4987,8 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_GULP_MISSILE: if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED) + && TARGET_TURN_DAMAGED + && IsBattlerAlive(battler)) { if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) { @@ -5013,7 +5014,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; } - SET_STATCHANGER(STAT_DEF, 1, TRUE); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; effect++; @@ -5057,9 +5057,8 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_GULP_MISSILE: - if ((effect = ShouldChangeFormHpBased(gBattlerAttacker)) - && ((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) - && IsBattlerAlive(gBattlerTarget)) + if (((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + && (effect = ShouldChangeFormHpBased(gBattlerAttacker))) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerFormChange; From d7e651696b86dd02965b922709d1e34539a05460 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 30 Sep 2021 10:30:46 -0300 Subject: [PATCH 109/136] Even more fixes -Changed the way in which Gulp Missile checks for a fainted opponent, just in case the reason why the attacker's defense wasn't being lowered is that the script was falling into BattleScript_GulpMissileNoSecondEffectGulping -Took into account max Defense stat stage, because I forgot to do that too. -Slightly changed the Defense reduction code, just in case. -Fixed the text string that was printed. Gulp Missile doesn't raise a stat, after all. -Fixed the script that was being called if the attacker has Clear Body, and also added jumps for Full Metal Body, White Smoke and Flower Veil. --- data/battle_scripts_1.s | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 0743d21c12..3c9397f986 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6012,7 +6012,8 @@ BattleScript_GulpMissileGorging:: healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER, FALSE, NULL - jumpifbyteequal gBattlerFainted, gBattlerAttacker, BattleScript_GulpMissileNoSecondEffectGorging + getbattlerfainted BS_ATTACKER + jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_GulpMissileNoSecondEffectGorging BattleScript_GulpMissileNoDmgGorging: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL @@ -6040,25 +6041,30 @@ BattleScript_GulpMissileGulping:: healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER, FALSE, NULL - jumpifbyteequal gBattlerFainted, gBattlerAttacker, BattleScript_GulpMissileNoSecondEffectGulping - jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileGulpingRet + getbattlerfainted BS_ATTACKER + jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_GulpMissileNoSecondEffectGulping + jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileNoSecondEffectGulping + jumpifability BS_ATTACKER, ABILITY_FULL_METAL_BODY, BattleScript_GulpMissileNoSecondEffectGulping + jumpifability BS_ATTACKER, ABILITY_WHITE_SMOKE, BattleScript_GulpMissileNoSecondEffectGulping + jumpifability BS_ATTACKER, ABILITY_FLOWER_VEIL, BattleScript_GulpMissileNoSecondEffectGulping BattleScript_GulpMissileNoDmgGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL waitanimation + playstatchangeanimation BS_ATTACKER, BIT_DEF, STAT_CHANGE_CANT_PREVENT | STAT_CHANGE_NEGATIVE setstatchanger STAT_DEF, 1, TRUE - statbuffchange STAT_BUFF_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, NULL - setgraphicalstatchangevalues - playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 - waitanimation - printstring STRINGID_ATTACKERSSTATROSE - waitmessage 0x40 + statbuffchange STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_GulpMissileGorgingTargetDefenseCantGoLower + printstring STRINGID_ATTACKERSSTATFELL + waitmessage B_WAIT_TIME_LONG return BattleScript_GulpMissileNoSecondEffectGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL waitanimation -BattleScript_GulpMissileGulpingRet: + return +BattleScript_GulpMissileGorgingTargetDefenseCantGoLower: + printstring STRINGID_STATSWONTDECREASE + waitmessage B_WAIT_TIME_LONG return BattleScript_PerishSongCountGoesDown:: From a506bf03c6a1b8af80e0ad34127e03db99c9bbde Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 1 Oct 2021 02:14:46 -0300 Subject: [PATCH 110/136] Corrected Flower Veil check --- asm/macros/battle_script.inc | 6 ++++++ data/battle_scripts_1.s | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 12cf20a9c0..f39818f7bc 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1925,6 +1925,12 @@ 1: .endm + .macro jumpifflowerveilattacker jumpptr:req + jumpifnottype BS_ATTACKER, TYPE_GRASS, 1f + jumpifability BS_ATTACKER_SIDE, ABILITY_FLOWER_VEIL, \jumpptr + 1: + .endm + .macro setallytonexttarget jumpptr:req jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f addbyte gBattlerTarget, 0x2 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3c9397f986..6324588b25 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6046,7 +6046,7 @@ BattleScript_GulpMissileGulping:: jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileNoSecondEffectGulping jumpifability BS_ATTACKER, ABILITY_FULL_METAL_BODY, BattleScript_GulpMissileNoSecondEffectGulping jumpifability BS_ATTACKER, ABILITY_WHITE_SMOKE, BattleScript_GulpMissileNoSecondEffectGulping - jumpifability BS_ATTACKER, ABILITY_FLOWER_VEIL, BattleScript_GulpMissileNoSecondEffectGulping + jumpifflowerveilattacker BattleScript_GulpMissileNoSecondEffectGulping BattleScript_GulpMissileNoDmgGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL From 43e73ac576fa67769f8d86dbd7674b6aee15c466 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 1 Oct 2021 05:25:25 -0300 Subject: [PATCH 111/136] Fixed Safari Zone --- src/battle_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 5c3f2ecd83..25db65f784 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3465,10 +3465,13 @@ static void TryDoEventsBeforeFirstTurn(void) return; // Set invalid mons as absent(for example when starting a double battle with only one pokemon). - for (i = 0; i < gBattlersCount; i++) + if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) { - if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE) - gAbsentBattlerFlags |= gBitTable[i]; + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE) + gAbsentBattlerFlags |= gBitTable[i]; + } } if (gBattleStruct->switchInAbilitiesCounter == 0) From f6917696474272a5a8fddd380ac4b26acbaf13ee Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 1 Oct 2021 06:29:21 -0300 Subject: [PATCH 112/136] Fixed Def stat reduction --- data/battle_scripts_1.s | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6324588b25..f1f5995ffb 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6051,11 +6051,14 @@ BattleScript_GulpMissileNoDmgGulping: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL waitanimation - playstatchangeanimation BS_ATTACKER, BIT_DEF, STAT_CHANGE_CANT_PREVENT | STAT_CHANGE_NEGATIVE + swapattackerwithtarget @ to make gStatDownStringIds down below print the right battler setstatchanger STAT_DEF, 1, TRUE statbuffchange STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_GulpMissileGorgingTargetDefenseCantGoLower - printstring STRINGID_ATTACKERSSTATFELL + setgraphicalstatchangevalues + playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG + swapattackerwithtarget @ restore the battlers, just in case return BattleScript_GulpMissileNoSecondEffectGulping: handleformchange BS_TARGET, 0 From f3ded43a88fb5561a0a52ce7d6ea98f5703a7f96 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 1 Oct 2021 22:32:48 -0300 Subject: [PATCH 113/136] Implemented Battle Bond --- data/battle_scripts_1.s | 13 +++++++++++++ include/battle_scripts.h | 1 + include/constants/battle_config.h | 2 ++ include/constants/battle_string_ids.h | 4 +++- src/battle_message.c | 5 ++++- src/battle_util.c | 20 ++++++++++++++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f1f5995ffb..f6f3d63cb1 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7711,6 +7711,19 @@ BattleScript_AbilityStatusEffect:: seteffectsecondary return +BattleScript_BattleBondActivatesOnMoveEndAttacker:: + pause 5 + copybyte gBattlerAbility, gBattlerAttacker + call BattleScript_AbilityPopUp + printstring STRINGID_ATTACKERBECAMEFULLYCHARGED + handleformchange BS_ATTACKER, 0 + handleformchange BS_ATTACKER, 1 + playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL + waitanimation + handleformchange BS_ATTACKER, 2 + printstring STRINGID_ATTACKERBECAMEASHGRENINJA + return + BattleScript_DancerActivates:: call BattleScript_AbilityPopUp waitmessage B_WAIT_TIME_SHORT diff --git a/include/battle_scripts.h b/include/battle_scripts.h index fbae42e24c..203be65198 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -388,5 +388,6 @@ extern const u8 BattleScript_ElectricTerrainPrevents[]; extern const u8 BattleScript_DarkTypePreventsPrankster[]; extern const u8 BattleScript_GulpMissileGorging[]; extern const u8 BattleScript_GulpMissileGulping[]; +extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 26007ff9f6..93202bed78 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -43,6 +43,8 @@ #define SPECIES_CRAMORANT 0 #define SPECIES_CRAMORANT_GORGING 10015 #define SPECIES_CRAMORANT_GULPING 10016 + #define SPECIES_GRENINJA_BATTLE_BOND 0 + #define SPECIES_GRENINJA_ASH 10017 #endif // Items with peculiar battle effects. diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index e32fd57780..144081974e 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -578,8 +578,10 @@ #define STRINGID_ATKGOTOVERINFATUATION 574 #define STRINGID_TORMENTEDNOMORE 575 #define STRINGID_HEALBLOCKEDNOMORE 576 +#define STRINGID_ATTACKERBECAMEFULLYCHARGED 577 +#define STRINGID_ATTACKERBECAMEASHGRENINJA 578 -#define BATTLESTRINGS_COUNT 577 +#define BATTLESTRINGS_COUNT 579 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. diff --git a/src/battle_message.c b/src/battle_message.c index ab10ceff06..cc89201410 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -704,10 +704,13 @@ static const u8 sText_EjectButtonActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} 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!"); - +static const u8 sText_AttackerBecameFullyCharged[] = _("{B_ATK_NAME_WITH_PREFIX} became fully charged\ndue to its bond with its trainer!\p"); +static const u8 sText_AttackerBecameAshGreninja[] = _("{B_ATK_NAME_WITH_PREFIX} became Ash-{B_ATK_NAME_WITH_PREFIX}!\p"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_ATTACKERBECAMEASHGRENINJA - 12] = sText_AttackerBecameAshGreninja, + [STRINGID_ATTACKERBECAMEFULLYCHARGED - 12] = sText_AttackerBecameFullyCharged, [STRINGID_HEALBLOCKEDNOMORE - 12] = sText_HealBlockedNoMore, [STRINGID_TORMENTEDNOMORE - 12] = sText_TormentedNoMore, [STRINGID_ATKGOTOVERINFATUATION - 12] = sText_AttackerGotOverInfatuation, diff --git a/src/battle_util.c b/src/battle_util.c index 20e5d91d1a..8898da5d75 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5065,6 +5065,16 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; + case ABILITY_BATTLE_BOND: + if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND + && gBattleResults.opponentFaintCounter != 0) + { + gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; + gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker; + } + break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -7562,6 +7572,15 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; } + // move-specific base power changes + switch (move) + { + case MOVE_WATER_SHURIKEN: + if (gBattleMons[battlerAtk].species == SPECIES_GRENINJA_ASH) + basePower = 20; + break; + } + if (basePower == 0) basePower = 1; return basePower; @@ -8726,6 +8745,7 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) {SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI}, {SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT}, {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT}, + {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND}, }; if (isSwitchingOut) // Don't revert Mimikyu Busted when switching out From c464b1b5dd88936df6edb54061a44dee2d64449a Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 1 Oct 2021 23:12:07 -0300 Subject: [PATCH 114/136] STRINGID_ATTACKERBECAMEASHGRENINJA -> STRINGID_ATTACKERBECAMEASHSPECIES --- data/battle_scripts_1.s | 2 +- include/constants/battle_string_ids.h | 2 +- src/battle_message.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f6f3d63cb1..5a9aec5251 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7721,7 +7721,7 @@ BattleScript_BattleBondActivatesOnMoveEndAttacker:: playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL waitanimation handleformchange BS_ATTACKER, 2 - printstring STRINGID_ATTACKERBECAMEASHGRENINJA + printstring STRINGID_ATTACKERBECAMEASHSPECIES return BattleScript_DancerActivates:: diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 144081974e..ff5eb5366f 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -579,7 +579,7 @@ #define STRINGID_TORMENTEDNOMORE 575 #define STRINGID_HEALBLOCKEDNOMORE 576 #define STRINGID_ATTACKERBECAMEFULLYCHARGED 577 -#define STRINGID_ATTACKERBECAMEASHGRENINJA 578 +#define STRINGID_ATTACKERBECAMEASHSPECIES 578 #define BATTLESTRINGS_COUNT 579 diff --git a/src/battle_message.c b/src/battle_message.c index cc89201410..b0ca25c959 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -705,11 +705,11 @@ static const u8 sText_AttackerGotOverInfatuation[] =_("{B_ATK_NAME_WITH_PREFIX} 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!"); static const u8 sText_AttackerBecameFullyCharged[] = _("{B_ATK_NAME_WITH_PREFIX} became fully charged\ndue to its bond with its trainer!\p"); -static const u8 sText_AttackerBecameAshGreninja[] = _("{B_ATK_NAME_WITH_PREFIX} became Ash-{B_ATK_NAME_WITH_PREFIX}!\p"); +static const u8 sText_AttackerBecameAshSpecies[] = _("{B_ATK_NAME_WITH_PREFIX} became Ash-{B_ATK_NAME_WITH_PREFIX}!\p"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { - [STRINGID_ATTACKERBECAMEASHGRENINJA - 12] = sText_AttackerBecameAshGreninja, + [STRINGID_ATTACKERBECAMEASHSPECIES - 12] = sText_AttackerBecameAshSpecies, [STRINGID_ATTACKERBECAMEFULLYCHARGED - 12] = sText_AttackerBecameFullyCharged, [STRINGID_HEALBLOCKEDNOMORE - 12] = sText_HealBlockedNoMore, [STRINGID_TORMENTEDNOMORE - 12] = sText_TormentedNoMore, From 611da31ae3d269a4f716f0fca7e4986aa53f1c95 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 2 Oct 2021 15:51:16 +1300 Subject: [PATCH 115/136] Fix form ID check The six here should be a seven, and replacing it with this function call is better than hard-coding it. --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a74cb3aaa7..fc9e9a66e2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7137,7 +7137,7 @@ u32 IsLeafGuardProtected(u32 battler) bool32 IsShieldsDownProtected(u32 battler) { return (gBattleMons[battler].ability == ABILITY_SHIELDS_DOWN - && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < 6); // Minior is not in core form + && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < GetFormIdFromFormSpeciesId(SPECIES_MINIOR_CORE_RED)); // Minior is not in core form } u32 IsAbilityStatusProtected(u32 battler) From 16d032e99d48ee58da7effba05d639f37e88acf8 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 02:01:34 -0300 Subject: [PATCH 116/136] Fix Unnerve not canceling out type resist berries. --- src/battle_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 20e5d91d1a..197bd6a25f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8203,6 +8203,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move u32 abilityDef = GetBattlerAbility(battlerDef); u32 defSide = GET_BATTLER_SIDE(battlerDef); u16 finalModifier = UQ_4_12(1.0); + u16 itemDef = gBattleMons[battlerDef].item; // check multiple targets in double battle if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2) @@ -8323,7 +8324,8 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move // berries reducing dmg case HOLD_EFFECT_RESIST_BERRY: if (moveType == GetBattlerHoldEffectParam(battlerDef) - && (moveType == TYPE_NORMAL || typeEffectivenessModifier >= UQ_4_12(2.0))) + && (moveType == TYPE_NORMAL || typeEffectivenessModifier >= UQ_4_12(2.0)) + && !UnnerveOn(battlerDef, itemDef)) { if (abilityDef == ABILITY_RIPEN) MulModifier(&finalModifier, UQ_4_12(0.25)); From 63c6e73eb89714c56b8358c705fbe6830bd1aa21 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 09:38:43 -0300 Subject: [PATCH 117/136] Fixed Sleep talk being canceled by the user being asleep.. --- 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 20e5d91d1a..e4bb55045d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3131,7 +3131,7 @@ u8 AtkCanceller_UnableToUseMove(void) gBattleMons[gBattlerAttacker].status1 -= toSub; if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) { - if (gCurrentMove != MOVE_SNORE && gCurrentMove != MOVE_SLEEP_TALK) + if (gChosenMove != MOVE_SNORE && gChosenMove != MOVE_SLEEP_TALK) { gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; From a18b9c5b3228ec2a39d514d40f4c67a5029f4d4c Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Sat, 2 Oct 2021 10:39:29 -0300 Subject: [PATCH 118/136] Quick tweaks -Use the species name for sText_AttackerBecameAshSpecies -Make Battle Bond not activate if the opposing party doesn't have 2 members or more. --- src/battle_message.c | 2 +- src/battle_script_commands.c | 3 ++- src/battle_util.c | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/battle_message.c b/src/battle_message.c index b0ca25c959..69829a731a 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -705,7 +705,7 @@ static const u8 sText_AttackerGotOverInfatuation[] =_("{B_ATK_NAME_WITH_PREFIX} 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!"); static const u8 sText_AttackerBecameFullyCharged[] = _("{B_ATK_NAME_WITH_PREFIX} became fully charged\ndue to its bond with its trainer!\p"); -static const u8 sText_AttackerBecameAshSpecies[] = _("{B_ATK_NAME_WITH_PREFIX} became Ash-{B_ATK_NAME_WITH_PREFIX}!\p"); +static const u8 sText_AttackerBecameAshSpecies[] = _("{B_ATK_NAME_WITH_PREFIX} became Ash-{B_BUFF1}!\p"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 40d84767e7..18302cba3c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8139,7 +8139,8 @@ static void Cmd_various(void) // Change species. if (gBattlescriptCurrInstr[3] == 0) { - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); + if (!gBattleTextBuff1) + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species); BtlController_EmitSetMonData(0, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], 2, &gBattleMons[gActiveBattler].species); MarkBattlerForControllerExec(gActiveBattler); } diff --git a/src/battle_util.c b/src/battle_util.c index 8898da5d75..d5c588e21b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5067,8 +5067,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move break; case ABILITY_BATTLE_BOND: if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND - && gBattleResults.opponentFaintCounter != 0) + && gBattleResults.opponentFaintCounter != 0 + && CalculateEnemyPartyCount() > 1) { + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species); gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; BattleScriptPushCursor(); From 57ea20bc6d7d951f42ac3535d70196471c5ecb0e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 13:32:36 -0300 Subject: [PATCH 119/136] Implemented modern effect of struggle with config --- data/battle_scripts_1.s | 7 +++++++ include/constants/battle.h | 3 ++- include/constants/battle_move_effects.h | 3 ++- src/battle_script_commands.c | 8 ++++++++ src/data/battle_moves.h | 3 ++- 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f1f5995ffb..92a03a55a1 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -379,6 +379,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectDecorate @ EFFECT_DECORATE .4byte BattleScript_EffectHit @ EFFECT_SNIPE_SHOT .4byte BattleScript_EffectTripleHit @ EFFECT_TRIPLE_HIT + .4byte BattleScript_EffectRecoilHP25 @ EFFECT_RECOIL_HP_25 BattleScript_EffectDecorate: attackcanceler @@ -4911,6 +4912,12 @@ BattleScript_EffectRecoil50: setmoveeffect MOVE_EFFECT_RECOIL_50 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN goto BattleScript_EffectHit +BattleScript_EffectRecoilHP25: + setmoveeffect MOVE_EFFECT_RECOIL_HP_25 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + jumpifnotmove MOVE_STRUGGLE, BattleScript_EffectHit + incrementgamestat GAME_STAT_USED_STRUGGLE + goto BattleScript_EffectHit + BattleScript_EffectTeeterDance:: attackcanceler attackstring diff --git a/include/constants/battle.h b/include/constants/battle.h index e88bb66dd7..bf6403a182 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -347,7 +347,8 @@ #define MOVE_EFFECT_THROAT_CHOP 0x43 #define MOVE_EFFECT_INCINERATE 0x44 #define MOVE_EFFECT_BUG_BITE 0x45 -#define NUM_MOVE_EFFECTS 0x46 +#define MOVE_EFFECT_RECOIL_HP_25 0x46 +#define NUM_MOVE_EFFECTS 0x47 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 440e6e76b6..5038b52c32 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -363,7 +363,8 @@ #define EFFECT_DECORATE 357 #define EFFECT_SNIPE_SHOT 358 #define EFFECT_TRIPLE_HIT 359 +#define EFFECT_RECOIL_HP_25 360 -#define NUM_BATTLE_MOVE_EFFECTS 360 +#define NUM_BATTLE_MOVE_EFFECTS 361 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1393a8d8c0..0eb1086af6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3177,6 +3177,14 @@ void SetMoveEffect(bool32 primary, u32 certain) BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilWithStatus; break; + case MOVE_EFFECT_RECOIL_HP_25: // Struggle + gBattleMoveDamage = (gBattleMons[gEffectBattler].maxHP) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; + break; case MOVE_EFFECT_THRASH: if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE) { diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index a7a2752e00..f63ef27fcb 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -2599,11 +2599,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = #if B_UPDATED_MOVE_DATA >= GEN_4 .accuracy = 0, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, + .effect = EFFECT_RECOIL_HP_25, #else .accuracy = 100, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, + .effect = EFFECT_RECOIL_25, #endif - .effect = EFFECT_RECOIL_25, .power = 50, .type = TYPE_NORMAL, .pp = 1, From 9aee8cbea501aaebf0f7bf12adf2db60d63f98b6 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 14:47:38 -0300 Subject: [PATCH 120/136] Fixed Sticky Hold not being negated by Gastro Acid when stealing and switching items --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1393a8d8c0..feff90aa43 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3067,7 +3067,7 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr++; } else if (gBattleMons[gBattlerTarget].item - && gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD) + && GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_NoItemSteal; @@ -11615,7 +11615,7 @@ static void Cmd_tryswapitems(void) // trick gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } // check if ability prevents swapping - else if (gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD) + else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) { gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; gLastUsedAbility = gBattleMons[gBattlerTarget].ability; From 6208995606442d51bd7fc8fbf0b1f0598f69f873 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 15:52:55 -0300 Subject: [PATCH 121/136] Fixed Run Away. --- src/battle_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_main.c b/src/battle_main.c index 25db65f784..62662d1e4f 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3685,7 +3685,7 @@ u8 IsRunningFromBattleImpossible(void) return 0; if (gBattleTypeFlags & BATTLE_TYPE_LINK) return 0; - if (gBattleMons[gActiveBattler].ability == ABILITY_RUN_AWAY) + if (GetBattlerAbility(gActiveBattler) == ABILITY_RUN_AWAY) return 0; if ((i = IsAbilityPreventingEscape(gActiveBattler))) From 5abb0c0dfeff902fe60656072d24106a0f9f2598 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 16:48:45 -0300 Subject: [PATCH 122/136] Fixed perish song + soundproof + gastro acid --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index feff90aa43..88157273a7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10899,7 +10899,7 @@ static void Cmd_trysetperishsong(void) for (i = 0; i < gBattlersCount; i++) { if (gStatuses3[i] & STATUS3_PERISH_SONG - || gBattleMons[i].ability == ABILITY_SOUNDPROOF + || GetBattlerAbility(i) == ABILITY_SOUNDPROOF || BlocksPrankster(gCurrentMove, gBattlerAttacker, i)) { notAffectedCount++; From 8d54e5666d5b6fa943fbc24cf86755ca5c4e599a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 17:05:23 -0300 Subject: [PATCH 123/136] Fixed waking up from uproar --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 88157273a7..88851909ba 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9121,7 +9121,7 @@ bool8 UproarWakeUpCheck(u8 battlerId) for (i = 0; i < gBattlersCount; i++) { - if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || gBattleMons[battlerId].ability == ABILITY_SOUNDPROOF) + if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || GetBattlerAbility(battlerId) == ABILITY_SOUNDPROOF) continue; gBattleScripting.battler = i; From ebe5e039986b2197f1b8bfbc8f4c949df0f78f64 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 17:07:29 -0300 Subject: [PATCH 124/136] Added Gen 8 abilities affected by Mold Breaker --- src/battle_util.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 20e5d91d1a..ae18d0a7dc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -983,6 +983,11 @@ static const u8 sAbilitiesAffectedByMoldBreaker[] = [ABILITY_FLUFFY] = 1, [ABILITY_QUEENLY_MAJESTY] = 1, [ABILITY_WATER_BUBBLE] = 1, + [ABILITY_MIRROR_ARMOR] = 1, + [ABILITY_PUNK_ROCK] = 1, + [ABILITY_ICE_SCALES] = 1, + [ABILITY_ICE_FACE] = 1, + [ABILITY_PASTEL_VEIL] = 1, }; static const u8 sAbilitiesNotTraced[ABILITIES_COUNT] = From b29f5c801fc793545088b5336964127ca0550e6d Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 18:16:14 -0300 Subject: [PATCH 125/136] Fixed Gastro Acid's effect on Early Bird --- 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 ae18d0a7dc..a346118869 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3126,7 +3126,7 @@ u8 AtkCanceller_UnableToUseMove(void) else { u8 toSub; - if (gBattleMons[gBattlerAttacker].ability == ABILITY_EARLY_BIRD) + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_EARLY_BIRD) toSub = 2; else toSub = 1; From a22a456268445be038cf3b35dbb0cfa0b1e1a921 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 18:21:02 -0300 Subject: [PATCH 126/136] Fixed heal bell + soundproof + gastro acid --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 88851909ba..713101765a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10770,7 +10770,7 @@ static void Cmd_healpartystatus(void) else party = gEnemyParty; - if (gBattleMons[gBattlerAttacker].ability != ABILITY_SOUNDPROOF) + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF) { gBattleMons[gBattlerAttacker].status1 = 0; gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_NIGHTMARE); @@ -10786,7 +10786,7 @@ static void Cmd_healpartystatus(void) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gAbsentBattlerFlags & gBitTable[gActiveBattler])) { - if (gBattleMons[gActiveBattler].ability != ABILITY_SOUNDPROOF) + if (GetBattlerAbility(gActiveBattler) != ABILITY_SOUNDPROOF) { gBattleMons[gActiveBattler].status1 = 0; gBattleMons[gActiveBattler].status2 &= ~(STATUS2_NIGHTMARE); From 9d64a26625f66b238735c9b8c15c641dd82326ab Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 18:31:09 -0300 Subject: [PATCH 127/136] Fix preasure + Gastro Acid --- src/battle_util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index a346118869..be88bda673 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1268,7 +1268,7 @@ void PressurePPLose(u8 target, u8 attacker, u16 move) { int moveIndex; - if (gBattleMons[target].ability != ABILITY_PRESSURE) + if (GetBattlerAbility(target) != ABILITY_PRESSURE) return; for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) @@ -1300,7 +1300,7 @@ void PressurePPLoseOnUsingImprison(u8 attacker) for (i = 0; i < gBattlersCount; i++) { - if (atkSide != GetBattlerSide(i) && gBattleMons[i].ability == ABILITY_PRESSURE) + if (atkSide != GetBattlerSide(i) && GetBattlerAbility(i) == ABILITY_PRESSURE) { for (j = 0; j < MAX_MON_MOVES; j++) { @@ -1333,7 +1333,7 @@ void PressurePPLoseOnUsingPerishSong(u8 attacker) for (i = 0; i < gBattlersCount; i++) { - if (gBattleMons[i].ability == ABILITY_PRESSURE && i != attacker) + if (GetBattlerAbility(i) == ABILITY_PRESSURE && i != attacker) { for (j = 0; j < MAX_MON_MOVES; j++) { From 2d5da7852cf396ad181da7bb4d7d9a0fcf93f646 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 18:44:04 -0300 Subject: [PATCH 128/136] Fixed Yawn + Vital Spirit + Gastro Acid --- src/battle_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index be88bda673..5c2de28c3d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2728,8 +2728,8 @@ u8 DoBattlerEndTurnEffects(void) { gStatuses3[gActiveBattler] -= STATUS3_YAWN_TURN(1); if (!(gStatuses3[gActiveBattler] & STATUS3_YAWN) && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY) - && gBattleMons[gActiveBattler].ability != ABILITY_VITAL_SPIRIT - && gBattleMons[gActiveBattler].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler) + && GetBattlerAbility(gActiveBattler) != ABILITY_VITAL_SPIRIT + && GetBattlerAbility(gActiveBattler) != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler) && !IsLeafGuardProtected(gActiveBattler)) { CancelMultiTurnMoves(gActiveBattler); From 978f73475b462def6c39320630ad2d0c6c988239 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 19:01:11 -0300 Subject: [PATCH 129/136] Config for Shadow Tag vs Shadow Tag --- include/constants/battle_config.h | 1 + src/battle_util.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 26007ff9f6..b2c8215137 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -127,6 +127,7 @@ #define B_GALE_WINGS GEN_7 // In Gen7+ requires full HP to trigger. #define B_STANCE_CHANGE_FAIL GEN_7 // In Gen7+, Stance Change fails if the Pokémon is unable to use a move because of confusion, paralysis, etc. In Gen6, it doesn't. #define B_GHOSTS_ESCAPE GEN_7 // In Gen6+, Ghost-type Pokémon can escape even when blocked by abilities such as Shadow Tag. +#define B_SHADOW_TAG_ESCAPE GEN_7 // In Gen4+, if both sides have a Pokémon with Shadow Tag, all battlers can escape. Before, neither side could escape this situation. #define B_MOODY_ACC_EVASION GEN_8 // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore. #define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before. #define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously. diff --git a/src/battle_util.c b/src/battle_util.c index 20e5d91d1a..d95a3fa835 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5387,11 +5387,15 @@ u32 IsAbilityOnFieldExcept(u32 battlerId, u32 ability) u32 IsAbilityPreventingEscape(u32 battlerId) { u32 id; - - if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battlerId, TYPE_GHOST)) - return 0; - - if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && gBattleMons[battlerId].ability != ABILITY_SHADOW_TAG) + #if B_GHOSTS_ESCAPE >= GEN_6 + if (IS_BATTLER_OF_TYPE(battlerId, TYPE_GHOST)) + return 0; + #endif + #if B_SHADOW_TAG_ESCAPE >= GEN_4 + if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && gBattleMons[battlerId].ability != ABILITY_SHADOW_TAG) + #else + if (id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) + #endif return id; if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_ARENA_TRAP)) && IsBattlerGrounded(battlerId)) return id; From 76bdbf164efe67bada54003b7d9a07d2d4df22a3 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 20:00:00 -0300 Subject: [PATCH 130/136] Updated sound flags for Howl and Heal Bell --- src/data/battle_moves.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index a7a2752e00..dea104b24b 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -3424,6 +3424,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_HEAL_BELL] = { + #if B_UPDATED_MOVE_DATA != GEN_5 + .flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND, + #else + .flags = FLAG_SNATCH_AFFECTED, + #endif .effect = EFFECT_HEAL_BELL, .power = 0, .type = TYPE_NORMAL, @@ -3432,7 +3437,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 0, .target = MOVE_TARGET_USER, .priority = 0, - .flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND, .split = SPLIT_STATUS, }, @@ -5338,6 +5342,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_HOWL] = { + #if B_UPDATED_MOVE_DATA >= GEN_8 + .flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND, + #else + .flags = FLAG_SNATCH_AFFECTED, + #endif .effect = EFFECT_ATTACK_UP, .power = 0, .type = TYPE_NORMAL, @@ -5346,7 +5355,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 0, .target = MOVE_TARGET_USER, .priority = 0, - .flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND, .split = SPLIT_STATUS, }, From 1e0ae9a1546c2d77a626324926d5b993ae1d29e8 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 2 Oct 2021 20:54:04 -0300 Subject: [PATCH 131/136] Tabs to spaces. --- 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 92a03a55a1..47a034ce1a 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -379,7 +379,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectDecorate @ EFFECT_DECORATE .4byte BattleScript_EffectHit @ EFFECT_SNIPE_SHOT .4byte BattleScript_EffectTripleHit @ EFFECT_TRIPLE_HIT - .4byte BattleScript_EffectRecoilHP25 @ EFFECT_RECOIL_HP_25 + .4byte BattleScript_EffectRecoilHP25 @ EFFECT_RECOIL_HP_25 BattleScript_EffectDecorate: attackcanceler From b3167b7d53cb4478b9f6d54e1745a188132169f0 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 19:40:36 -0300 Subject: [PATCH 132/136] Fixed Trump Card's damage check --- 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 462b58bd48..71a9a31301 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7489,7 +7489,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (gBattleMons[battlerAtk].pp[i] >= ARRAY_COUNT(sTrumpCardPowerTable)) basePower = sTrumpCardPowerTable[ARRAY_COUNT(sTrumpCardPowerTable) - 1]; else - basePower = sTrumpCardPowerTable[i]; + basePower = sTrumpCardPowerTable[gBattleMons[battlerAtk].pp[i]]; } break; case EFFECT_ACROBATICS: From 4ab8c95207b679a92e713a2a35a26c0121e611be Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 20:17:43 -0300 Subject: [PATCH 133/136] Fixed Heat Crash's power table name --- src/battle_util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 462b58bd48..09a2ae0ae2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7317,7 +7317,7 @@ static const u16 sWeightToDamageTable[] = }; static const u8 sSpeedDiffPowerTable[] = {40, 60, 80, 120, 150}; -static const u8 sHeatCrushPowerTable[] = {40, 40, 60, 80, 100, 120}; +static const u8 sHeatCrashPowerTable[] = {40, 40, 60, 80, 100, 120}; static const u8 sTrumpCardPowerTable[] = {200, 80, 60, 50, 40}; const struct TypePower gNaturalGiftTable[] = @@ -7512,10 +7512,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_HEAT_CRASH: weight = GetBattlerWeight(battlerAtk) / GetBattlerWeight(battlerDef); - if (weight >= ARRAY_COUNT(sHeatCrushPowerTable)) - basePower = sHeatCrushPowerTable[ARRAY_COUNT(sHeatCrushPowerTable) - 1]; + if (weight >= ARRAY_COUNT(sHeatCrashPowerTable)) + basePower = sHeatCrashPowerTable[ARRAY_COUNT(sHeatCrashPowerTable) - 1]; else - basePower = sHeatCrushPowerTable[i]; + basePower = sHeatCrashPowerTable[i]; break; case EFFECT_PUNISHMENT: basePower = 60 + (CountBattlerStatIncreases(battlerDef, FALSE) * 20); From 92f0f6f82013329fcc133cc47fa6bb206c03a72c Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 4 Oct 2021 20:20:00 -0300 Subject: [PATCH 134/136] Fixed Psychic Fangs power --- src/data/battle_moves.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index a7a2752e00..84ba59f24c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10226,7 +10226,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_PSYCHIC_FANGS] = { .effect = EFFECT_BRICK_BREAK, - .power = 75, + .power = 85, .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 15, From a6198e5d4682d284a6259467505ffd947280cbcb Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 6 Oct 2021 15:30:52 +1300 Subject: [PATCH 135/136] Fix Simple Beam - No longer freezes the game - Now fails if the target already has simple - Explicitly checks and changes the target's ability instead of gActiveBattler's ability --- 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 8d6dd5bdb2..ead08479a0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7910,15 +7910,15 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; return; case VARIOUS_SET_SIMPLE_BEAM: - if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gActiveBattler].ability)) + if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gBattlerTarget].ability) + || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); } else { - gBattleMons[gActiveBattler].ability = ABILITY_SIMPLE; + gBattleMons[gBattlerTarget].ability = ABILITY_SIMPLE; gBattlescriptCurrInstr += 7; - break; } return; case VARIOUS_TRY_ENTRAINMENT: From 38b816ccdd8b7ac345c628ee93a8bb62aa9b2c92 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Wed, 6 Oct 2021 21:53:30 +1300 Subject: [PATCH 136/136] AI handles dynamic move types This will make the AI account for the type of moves like Weather Ball, Hidden Power and Revelation Dance when considering abilities that make the useless. E.g. Water-type Hidden Power vs. Storm Drain. --- src/battle_ai_main.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 03472271d1..42b8b9d408 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -520,6 +520,9 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) u32 i; u16 predictedMove = gLastMoves[battlerDef]; // TODO better move prediction + SetTypeBeforeUsingMove(move, battlerAtk); + GET_MOVE_TYPE(move, moveType); + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; @@ -2472,7 +2475,10 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) bool32 attackerHasBadAbility = (GetAbilityRating(AI_DATA->atkAbility) < 0); bool32 partnerHasBadAbility = (GetAbilityRating(atkPartnerAbility) < 0); u16 predictedMove = gLastMoves[battlerDef]; //for now - + + SetTypeBeforeUsingMove(move, battlerAtk); + GET_MOVE_TYPE(move, moveType); + // check what effect partner is using if (AI_DATA->partnerMove != 0) { @@ -4751,7 +4757,10 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) { u16 effect = gBattleMoves[move].effect; u8 moveType = gBattleMoves[move].type; - + + SetTypeBeforeUsingMove(move, battlerAtk); + GET_MOVE_TYPE(move, moveType); + if (IsTargetingPartner(battlerAtk, battlerDef)) { if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY)