diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 062ac9880..503f38d08 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1877,6 +1877,10 @@ .2byte \species .4byte \ptr .endm + + .macro tryendneutralizinggas battler:req + various \battler, VARIOUS_TRY_END_NEUTRALIZING_GAS + .endm .macro trytoapplymimicry battler:req, ptr:req various \battler, VARIOUS_TRY_TO_APPLY_MIMICRY diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index b10c937ae..350ba2cc0 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -2506,20 +2506,30 @@ Move_GIGA_IMPACT: loadspritegfx ANIM_TAG_IMPACT monbg ANIM_DEF_PARTNER setalpha 12, 8 + createvisualtask AnimTask_IsContest, 2 + jumprettrue SetGigaImpactContestsBG + createvisualtask AnimTask_IsTargetPlayerSide, 2 + jumpretfalse SetGigaImpactOpponentBG + goto SetGigaImpactPlayerBG +SetGigaImpactOpponentBG: + fadetobg BG_GIGA_IMPACT_OPPONENT + goto GigaImpactContinuity +SetGigaImpactPlayerBG: + fadetobg BG_GIGA_IMPACT_PLAYER + goto GigaImpactContinuity +SetGigaImpactContestsBG: + fadetobg BG_GIGA_IMPACT_CONTEST + goto GigaImpactContinuity +GigaImpactContinuity: playsewithpan SE_M_TAKE_DOWN, SOUND_PAN_ATTACKER createsprite gVerticalDipSpriteTemplate, ANIM_ATTACKER, 2, 6, 1, ANIM_ATTACKER waitforvisualfinish delay 11 createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 26, 0, 0, 5 delay 6 - @monbg ANIM_DEF_PARTNER - @setalpha 12, 8 - @createvisualtask AnimTask_WindUpLunge, 5, 7, 0, -18, 8, 23, 10, 40, 10 - @delay 35 - createsprite gComplexPaletteBlendSpriteTemplate, 2, 7, 31, 3, 1, 0, 10, 0, 0 + waitbgfadeout createsprite gBasicHitSplatSpriteTemplate, 4, 4, -10, 0, 1, 0 playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET - call SetImpactBackground delay 1 createsprite gSlideMonToOffsetSpriteTemplate 2, 5, 1, -16, 0, 0, 4 waitforvisualfinish @@ -2534,6 +2544,7 @@ Move_GIGA_IMPACT: blendoff restorebg waitbgfadein + waitforvisualfinish end Move_NASTY_PLOT: @@ -7279,7 +7290,7 @@ Move_RELIC_SONG: monbg ANIM_DEF_PARTNER launchtask AnimTask_MusicNotesRainbowBlend 0x2 0x0 waitforvisualfinish - panse_1B 0x1DF, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 0x2, 0x0 @ ??? + createvisualtask SoundTask_PlayCryWithEcho, 2, ANIM_ATTACKER, 2 launchtask AnimTask_UproarDistortion 0x2 0x1 0x0 launchtemplate gUproarRingSpriteTemplate 0x3 0x6 0x0 0x0 0x0 0x0 0x1f 0x8 launchtemplate gJaggedMusicNoteSpriteTemplate 0x2 0x4 0x0 0x1d 0xfff4 0x0 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index cc43b0872..d2d22db6e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2163,6 +2163,7 @@ BattleScript_EffectSimpleBeam: trytoclearprimalweather printstring STRINGID_EMPTYSTRING3 waitmessage 1 + tryendneutralizinggas BS_TARGET goto BattleScript_MoveEnd BattleScript_EffectSuckerPunch: @@ -2385,6 +2386,7 @@ BattleScript_EffectGastroAcid: trytoclearprimalweather printstring STRINGID_EMPTYSTRING3 waitmessage 1 + tryendneutralizinggas BS_TARGET goto BattleScript_MoveEnd BattleScript_EffectToxicSpikes: @@ -8270,6 +8272,12 @@ BattleScript_SwitchInAbilityMsg:: waitmessage B_WAIT_TIME_LONG end3 +BattleScript_SwitchInAbilityMsgRet:: + call BattleScript_AbilityPopUp + printfromtable gSwitchInAbilityStringIds + waitmessage B_WAIT_TIME_LONG + return + BattleScript_ActivateAsOne:: call BattleScript_AbilityPopUp printfromtable gSwitchInAbilityStringIds @@ -9125,3 +9133,19 @@ BattleScript_PastelVeilLoopIncrement: goto BattleScript_PastelVeilEnd BattleScript_PastelVeilEnd: end3 + +sByteFour: +.byte MAX_BATTLERS_COUNT + +BattleScript_NeutralizingGasExits:: + savetarget + pause B_WAIT_TIME_SHORT + printstring STRINGID_NEUTRALIZINGGASOVER + waitmessage B_WAIT_TIME_LONG + setbyte gBattlerTarget, 0 +BattleScript_NeutralizingGasExitsLoop: + switchinabilities BS_TARGET + addbyte gBattlerTarget, 1 + jumpifbytenotequal gBattlerTarget, sByteFour, BattleScript_NeutralizingGasExitsLoop @ SOMEHOW, comparing to gBattlersCount is problematic. + restoretarget + return diff --git a/graphics/battle_anims/backgrounds/giga_impact.pal b/graphics/battle_anims/backgrounds/giga_impact.pal deleted file mode 100644 index 944174076..000000000 --- a/graphics/battle_anims/backgrounds/giga_impact.pal +++ /dev/null @@ -1,19 +0,0 @@ -JASC-PAL -0100 -16 -0 0 0 -255 214 0 -255 197 0 -255 173 0 -255 165 0 -148 90 222 -255 107 0 -255 132 0 -255 148 0 -255 156 41 -0 0 0 -0 90 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 diff --git a/graphics/battle_anims/backgrounds/new/giga_impact.pal b/graphics/battle_anims/backgrounds/new/giga_impact.pal new file mode 100644 index 000000000..06f02604a --- /dev/null +++ b/graphics/battle_anims/backgrounds/new/giga_impact.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +0 0 0 +240 136 184 +232 104 168 +136 8 40 +248 24 104 +216 32 96 +224 72 136 +160 0 48 +216 0 64 +200 40 88 +192 0 56 +176 32 128 +176 24 72 +152 16 56 +200 48 80 +216 56 160 diff --git a/graphics/battle_anims/backgrounds/new/giga_impact.png b/graphics/battle_anims/backgrounds/new/giga_impact.png new file mode 100644 index 000000000..0d5d705fe Binary files /dev/null and b/graphics/battle_anims/backgrounds/new/giga_impact.png differ diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_contest.bin b/graphics/battle_anims/backgrounds/new/giga_impact_contest.bin new file mode 100644 index 000000000..03c709bb9 --- /dev/null +++ b/graphics/battle_anims/backgrounds/new/giga_impact_contest.bin @@ -0,0 +1,3 @@ +$$$$$$$$$ D!E!F!G!H!I!@!$$$$$$$$$ $$$$$$$$$ +! ! ! !!!!$$$$$$$$$ !!!!!!!$$$$$$$$$ *!+!,!-!.!/!"!$$$$$$$$$ :!;!!?!2!$$$$$$$$$ J!K!L!M!N!O!B!,,,,,,,,,((((((((((((((((J)K)L)M)N)O)B),,,,,,,,,((((((((((((((((:);)<)=)>)?)2),,,,,,,,,((((((((((((((((*)+),)-).)/)"),,,,,,,,,(((((((((((((((())))))),,,,,,,,,(((((((((((((((( +) ) ) )))),,,,,,,,,(((((((((((((((((((((((,,,,,,,,,((((((((((((((((D)E)F)G)H)I)@) \ No newline at end of file diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin b/graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin index a55ff2f56..0cfa1f1ec 100644 Binary files a/graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin and b/graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin differ diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_opponent.pal b/graphics/battle_anims/backgrounds/new/giga_impact_opponent.pal deleted file mode 100644 index 2fdba24f6..000000000 --- a/graphics/battle_anims/backgrounds/new/giga_impact_opponent.pal +++ /dev/null @@ -1,19 +0,0 @@ -JASC-PAL -0100 -16 -41 49 49 -106 139 189 -246 131 180 -255 0 255 -255 16 98 -238 98 164 -230 65 131 -222 0 57 -222 24 90 -205 41 74 -205 32 82 -189 0 49 -172 16 65 -156 0 41 -148 16 49 -131 8 32 diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_opponent.png b/graphics/battle_anims/backgrounds/new/giga_impact_opponent.png deleted file mode 100644 index cfa8c07c8..000000000 Binary files a/graphics/battle_anims/backgrounds/new/giga_impact_opponent.png and /dev/null differ diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_player.bin b/graphics/battle_anims/backgrounds/new/giga_impact_player.bin index bfee2cb88..3b89218e0 100644 Binary files a/graphics/battle_anims/backgrounds/new/giga_impact_player.bin and b/graphics/battle_anims/backgrounds/new/giga_impact_player.bin differ diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_player.pal b/graphics/battle_anims/backgrounds/new/giga_impact_player.pal deleted file mode 100644 index ea01813a9..000000000 --- a/graphics/battle_anims/backgrounds/new/giga_impact_player.pal +++ /dev/null @@ -1,19 +0,0 @@ -JASC-PAL -0100 -16 -0 0 0 -255 255 255 -255 0 255 -255 16 98 -246 131 180 -238 98 164 -230 65 131 -222 0 57 -222 24 90 -205 32 82 -205 41 74 -189 0 49 -172 16 65 -156 0 41 -148 16 49 -131 8 32 diff --git a/graphics/battle_anims/backgrounds/new/giga_impact_player.png b/graphics/battle_anims/backgrounds/new/giga_impact_player.png deleted file mode 100644 index b258035e3..000000000 Binary files a/graphics/battle_anims/backgrounds/new/giga_impact_player.png and /dev/null differ diff --git a/graphics/battle_anims/backgrounds/new/spacial_rend_opponent.bin b/graphics/battle_anims/backgrounds/new/spacial_rend_opponent.bin deleted file mode 100644 index 0cfa1f1ec..000000000 --- a/graphics/battle_anims/backgrounds/new/spacial_rend_opponent.bin +++ /dev/null @@ -1,3 +0,0 @@ -@%I%H%G%F%E%D%$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$ %%% % % % -%$$$$$$$$$$$$$$$$ %%%%%%%$$$$$$$$$$$$$$$$ "%/%.%-%,%+%*%$$$$$$$$$$$$$$$$ 2%?%>%=%<%;%:%$$$$$$$$$$$$$$$$ B%O%N%M%L%K%J%$$$$$$$$$$$$$$$$ B-O-N-M-L-K-J-,,,,,,,,,,,,,,,,(((((((((2-?->-=-<-;-:-,,,,,,,,,,,,,,,,((((((((("-/-.---,-+-*-,,,,,,,,,,,,,,,,(((((((((-------,,,,,,,,,,,,,,,,(((((((((--- - - - --,,,,,,,,,,,,,,,,(((((((((,,,,,,,,,,,,,,,,,,,,,,,(((((((((@-I-H-G-F-E-D-,,,,,,,,,,,,,,,,((((((((( \ No newline at end of file diff --git a/graphics/battle_anims/backgrounds/new/spacial_rend_player.bin b/graphics/battle_anims/backgrounds/new/spacial_rend_player.bin deleted file mode 100644 index 3b89218e0..000000000 Binary files a/graphics/battle_anims/backgrounds/new/spacial_rend_player.bin and /dev/null differ diff --git a/include/battle.h b/include/battle.h index 40d884b35..a6ce1875f 100644 --- a/include/battle.h +++ b/include/battle.h @@ -62,12 +62,13 @@ struct ResourceFlags u32 flags[4]; }; -#define RESOURCE_FLAG_FLASH_FIRE 0x1 -#define RESOURCE_FLAG_ROOST 0x2 -#define RESOURCE_FLAG_UNBURDEN 0x4 -#define RESOURCE_FLAG_INTIMIDATED 0x8 -#define RESOURCE_FLAG_TRACED 0x10 -#define RESOURCE_FLAG_EMERGENCY_EXIT 0x20 +#define RESOURCE_FLAG_FLASH_FIRE 0x1 +#define RESOURCE_FLAG_ROOST 0x2 +#define RESOURCE_FLAG_UNBURDEN 0x4 +#define RESOURCE_FLAG_INTIMIDATED 0x8 +#define RESOURCE_FLAG_TRACED 0x10 +#define RESOURCE_FLAG_EMERGENCY_EXIT 0x20 +#define RESOURCE_FLAG_NEUTRALIZING_GAS 0x40 struct DisableStruct { @@ -189,6 +190,8 @@ struct SpecialStatus u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute. u8 dancerUsedMove:1; u8 dancerOriginalTarget:3; + u8 announceNeutralizingGas:1; // See Cmd_switchineffects + u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS s32 dmg; s32 physicalDmg; s32 specialDmg; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 7fe96ad95..a3e53ee99 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -261,6 +261,7 @@ extern const u8 BattleScript_AttackerAbilityStatRaiseEnd3[]; extern const u8 BattleScript_PoisonHealActivates[]; extern const u8 BattleScript_BadDreamsActivates[]; extern const u8 BattleScript_SwitchInAbilityMsg[]; +extern const u8 BattleScript_SwitchInAbilityMsgRet[]; extern const u8 BattleScript_ToxicSpikesPoisoned[]; extern const u8 BattleScript_ToxicSpikesAbsorbed[]; extern const u8 BattleScript_StickyWebOnSwitchIn[]; @@ -413,6 +414,7 @@ extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[]; extern const u8 BattleScript_AttackerFormChangeMoveEffect[]; extern const u8 BattleScript_BothCanNoLongerEscape[]; extern const u8 BattleScript_OctolockEndTurn[]; +extern const u8 BattleScript_NeutralizingGasExits[]; extern const u8 BattleScript_MultiHitPrintStrings[]; extern const u8 BattleScript_BurnUpRemoveType[]; diff --git a/include/battle_util.h b/include/battle_util.h index 74ad8022a..f5485389e 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -8,21 +8,23 @@ #define MOVE_LIMITATION_TAUNT (1 << 4) #define MOVE_LIMITATION_IMPRISON (1 << 5) -#define ABILITYEFFECT_ON_SWITCHIN 0x0 -#define ABILITYEFFECT_ENDTURN 0x1 -#define ABILITYEFFECT_MOVES_BLOCK 0x2 -#define ABILITYEFFECT_ABSORBING 0x3 -#define ABILITYEFFECT_MOVE_END_ATTACKER 0x4 -#define ABILITYEFFECT_MOVE_END 0x5 -#define ABILITYEFFECT_IMMUNITY 0x6 -#define ABILITYEFFECT_FORECAST 0x7 -#define ABILITYEFFECT_SYNCHRONIZE 0x8 -#define ABILITYEFFECT_ATK_SYNCHRONIZE 0x9 -#define ABILITYEFFECT_INTIMIDATE1 0xA -#define ABILITYEFFECT_INTIMIDATE2 0xB -#define ABILITYEFFECT_TRACE1 0xC -#define ABILITYEFFECT_TRACE2 0xD -#define ABILITYEFFECT_MOVE_END_OTHER 0xE +#define ABILITYEFFECT_ON_SWITCHIN 0 +#define ABILITYEFFECT_ENDTURN 1 +#define ABILITYEFFECT_MOVES_BLOCK 2 +#define ABILITYEFFECT_ABSORBING 3 +#define ABILITYEFFECT_MOVE_END_ATTACKER 4 +#define ABILITYEFFECT_MOVE_END 5 +#define ABILITYEFFECT_IMMUNITY 6 +#define ABILITYEFFECT_FORECAST 7 +#define ABILITYEFFECT_SYNCHRONIZE 8 +#define ABILITYEFFECT_ATK_SYNCHRONIZE 9 +#define ABILITYEFFECT_INTIMIDATE1 10 +#define ABILITYEFFECT_INTIMIDATE2 11 +#define ABILITYEFFECT_TRACE1 12 +#define ABILITYEFFECT_TRACE2 13 +#define ABILITYEFFECT_MOVE_END_OTHER 14 +#define ABILITYEFFECT_NEUTRALIZINGGAS 15 +// Special cases #define ABILITYEFFECT_SWITCH_IN_TERRAIN 0xFE #define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF @@ -102,6 +104,7 @@ u32 IsAbilityOnOpposingSide(u32 battlerId, u32 ability); u32 IsAbilityOnField(u32 ability); u32 IsAbilityOnFieldExcept(u32 battlerId, u32 ability); u32 IsAbilityPreventingEscape(u32 battlerId); +bool32 IsBattlerProtected(u8 battlerId, u16 move); bool32 CanBattlerEscape(u32 battlerId); // no ability check void BattleScriptExecute(const u8* BS_ptr); void BattleScriptPushCursorAndCallback(const u8* BS_ptr); diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 0f6f277c7..ea426cc80 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -51,6 +51,7 @@ #define SPECIES_MELOETTA_PIROUETTE 10019 #define SPECIES_MORPEKO 0 #define SPECIES_MORPEKO_HANGRY 10020 + #define SPECIES_SIRFETCHD 10021 #endif // Items with peculiar battle effects. @@ -114,6 +115,7 @@ #define B_PAYBACK_SWITCH_BOOST GEN_7 // In Gen5+, if the opponent switches out, Payback's damage will no longer be doubled. #define B_HIDDEN_POWER_DMG GEN_7 // In Gen6+, Hidden Power's base power was set to always be 60. Before, it was determined by the mon's IVs. #define B_ROUGH_SKIN_DMG GEN_7 // In Gen4+, Rough Skin contact damage is 1/8th of max HP instead of 1/16th. This will also affect Iron Barbs. +#define B_KNOCK_OFF_DMG GEN_8 // In Gen6+, Knock Off deals 50% more damage when knocking off an item #define B_BEAT_UP_DMG GEN_8 // In Gen5+, Beat Up uses a different formula to calculate the damage of each hit, and deals Dark-type damage. // Type settings @@ -154,6 +156,7 @@ #define B_GLARE_GHOST GEN_7 // In Gen4+, Glare can hit Ghost-type Pokémon normally. #define B_SKILL_SWAP GEN_7 // In Gen4+, Skill Swap triggers switch-in abilities after use. #define B_BRICK_BREAK GEN_7 // In Gen4+, you can destroy your own side's screens. In Gen 5+, screens are not removed if the target is immune. +#define B_WISH_HP_SOURCE GEN_7 // In Gen5+, Wish heals half of the user's max HP instead of the target's. // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. @@ -185,6 +188,7 @@ #define B_HEAVY_BALL_MODIFIER GEN_7 // In Gen7+, Heavy Ball's ranges change. See Cmd_handleballthrow. #define B_DREAM_BALL_MODIFIER GEN_8 // In Gen8, Dream Ball's catch multiplier is x4 when the target is asleep or has the ability Comatose. #define B_SERENE_GRACE_BOOST GEN_7 // In Gen5+, Serene Grace boosts the added flinch chance of King's Rock and Razor Fang. +#define B_LEEK_ALWAYS_CRIT GEN_7 // In Gen6+, if a Farfetch'd or Sirfetch'd holding a Leek use a move with increased Critical Hit ratio, it will always result in a Critical Hit. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 3c919da19..775719b17 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -207,8 +207,8 @@ #define VARIOUS_CHECK_POLTERGEIST 134 #define VARIOUS_SET_OCTOLOCK 135 #define VARIOUS_CUT_1_3_HP_RAISE_STATS 136 -#define VARIOUS_IS_PARENTAL_BOND_LAST_STRIKE 137 - +#define VARIOUS_TRY_END_NEUTRALIZING_GAS 137 +#define VARIOUS_IS_PARENTAL_BOND_LAST_STRIKE 138 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index d439e3e7f..7846fa521 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -607,8 +607,10 @@ #define STRINGID_PKMNBECAMEWEAKERTOFIRE 604 #define STRINGID_ABOUTTOUSEPOLTERGEIST 605 #define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 606 +#define STRINGID_NEUTRALIZINGGASENTERS 607 +#define STRINGID_NEUTRALIZINGGASOVER 608 -#define BATTLESTRINGS_COUNT 607 +#define BATTLESTRINGS_COUNT 609 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. @@ -844,6 +846,7 @@ #define B_MSG_SWITCHIN_ASONE 13 #define B_MSG_SWITCHIN_CURIOUS_MEDICINE 14 #define B_MSG_SWITCHIN_PASTEL_VEIL 15 +#define B_MSG_SWITCHIN_NEUTRALIZING_GAS 16 // gMentalHerbCureStringIds #define B_MSG_MENTALHERBCURE_INFATUATION 0 diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index d7d74d3e1..cba2321ce 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -62,12 +62,12 @@ #define HOLD_EFFECT_FIRE_POWER 58 #define HOLD_EFFECT_DRAGON_POWER 59 #define HOLD_EFFECT_NORMAL_POWER 60 -#define HOLD_EFFECT_UP_GRADE 61 +#define HOLD_EFFECT_UPGRADE 61 #define HOLD_EFFECT_SHELL_BELL 62 #define HOLD_EFFECT_LUCKY_PUNCH 63 #define HOLD_EFFECT_METAL_POWDER 64 #define HOLD_EFFECT_THICK_CLUB 65 -#define HOLD_EFFECT_STICK 66 +#define HOLD_EFFECT_LEEK 66 // Gen4 hold effects. #define HOLD_EFFECT_CHOICE_SCARF 67 diff --git a/include/graphics.h b/include/graphics.h index 34eef131e..efb57bfde 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -4937,10 +4937,13 @@ extern const u32 gBattleAnimBgImage_Hurricane[]; extern const u32 gBattleAnimBgPalette_Hurricane[]; extern const u32 gBattleAnimBgTilemap_Hurricane[]; extern const u32 gBattleAnimBgPalette_RockWrecker[]; +extern const u32 gBattleAnimBgTilemap_GigaImpactPlayer[]; +extern const u32 gBattleAnimBgTilemap_GigaImpactOpponent[]; +extern const u32 gBattleAnimBgTilemap_GigaImpactContest[]; +extern const u32 gBattleAnimBgImage_GigaImpact[]; +extern const u32 gBattleAnimBgPalette_GigaImpact[]; extern const u32 gBattleAnimBgImage_SpacialRend[]; extern const u32 gBattleAnimBgPalette_SpacialRend[]; -extern const u32 gBattleAnimBgTilemap_SpacialRendOpponent[]; -extern const u32 gBattleAnimBgTilemap_SpacialRendPlayer[]; extern const u32 gBattleAnimBgPalette_DarkVoid[]; extern const u32 gBattleAnimBgTilemap_DarkVoid[]; extern const u32 gBattleAnimBgPalette_Dark[]; @@ -4960,7 +4963,6 @@ extern const u32 gBattleAnimBgPalette_Fissure[]; extern const u32 gBattleAnimBgPalette_Bug[]; extern const u32 gBattleAnimBgPalette_Solarbeam[]; extern const u32 gBattleAnimBgPalette_MagmaStorm[]; -extern const u32 gBattleAnimBgPalette_GigaImpact[]; extern const u32 gBattleAnimBgPalette_TrickRoom[]; extern const u32 gBattleAnimBgTilemap_Dark[]; extern const u32 gBattleAnimBgTilemap_Ghost[]; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 547b1a211..9b93337d4 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2320,7 +2320,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) || IsInstructBannedMove(instructedMove) || MoveRequiresRecharging(instructedMove) || MoveCallsOtherMove(instructedMove) - #ifdef ITEM_Z_RING + #ifdef ITEM_Z_POWER_RING //|| (IsZMove(instructedMove)) #endif || (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index e8e399935..400876cc9 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -82,7 +82,7 @@ static bool8 ShouldSwitchIfWonderGuard(void) opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler)); - if (gBattleMons[GetBattlerAtPosition(opposingPosition)].ability != ABILITY_WONDER_GUARD) + if (GetBattlerAbility(GetBattlerAtPosition(opposingPosition)) != ABILITY_WONDER_GUARD) return FALSE; // Check if Pokemon has a super effective move. @@ -176,7 +176,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void) else return FALSE; - if (gBattleMons[gActiveBattler].ability == absorbingTypeAbility) + if (AI_GetAbility(gActiveBattler) == absorbingTypeAbility) return FALSE; GetAIPartyIndexes(gActiveBattler, &firstId, &lastId); @@ -228,7 +228,7 @@ static bool8 ShouldSwitchIfNaturalCure(void) { if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)) return FALSE; - if (gBattleMons[gActiveBattler].ability != ABILITY_NATURAL_CURE) + if (AI_GetAbility(gActiveBattler) != ABILITY_NATURAL_CURE) return FALSE; if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 2) return FALSE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 71dc78d0a..47561c765 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1121,19 +1121,24 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability) // does NOT include ability suppression checks s32 AI_GetAbility(u32 battlerId) { + u32 knownAbility = GetBattlerAbility(battlerId); + // The AI knows its own ability. if (IsBattlerAIControlled(battlerId)) - return gBattleMons[battlerId].ability; + return knownAbility; + + // Check neutralizing gas, gastro acid + if (knownAbility == ABILITY_NONE) + return knownAbility; if (BATTLE_HISTORY->abilities[battlerId] != ABILITY_NONE) return BATTLE_HISTORY->abilities[battlerId]; - // Abilities that prevent fleeing. - if (gBattleMons[battlerId].ability == ABILITY_SHADOW_TAG - || gBattleMons[battlerId].ability == ABILITY_MAGNET_PULL - || gBattleMons[battlerId].ability == ABILITY_ARENA_TRAP) - return gBattleMons[battlerId].ability; + // Abilities that prevent fleeing - treat as always known + if (knownAbility == ABILITY_SHADOW_TAG || knownAbility == ABILITY_MAGNET_PULL || knownAbility == ABILITY_ARENA_TRAP) + return knownAbility; + // Else, guess the ability if (gBaseStats[gBattleMons[battlerId].species].abilities[0] != ABILITY_NONE) { if (gBaseStats[gBattleMons[battlerId].species].abilities[1] != ABILITY_NONE) @@ -1146,6 +1151,7 @@ s32 AI_GetAbility(u32 battlerId) return gBaseStats[gBattleMons[battlerId].species].abilities[0]; // It's definitely ability 1. } } + return ABILITY_NONE; // Unknown. } @@ -2408,9 +2414,19 @@ static bool32 AnyUsefulStatIsRaised(u8 battler) return FALSE; } +struct Pokemon *GetPartyBattlerPartyData(u8 battlerId, u8 switchBattler) +{ + struct Pokemon *mon; + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + mon = &gPlayerParty[switchBattler]; + else + mon = &gEnemyParty[switchBattler]; + return mon; +} + static bool32 PartyBattlerShouldAvoidHazards(u8 currBattler, u8 switchBattler) { - struct Pokemon *mon = GetBattlerPartyData(switchBattler); + struct Pokemon *mon = GetPartyBattlerPartyData(currBattler, switchBattler); u16 ability = GetMonAbility(mon); // we know our own party data u16 holdEffect = GetBattlerHoldEffect(GetMonData(mon, MON_DATA_HELD_ITEM), TRUE); u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); diff --git a/src/battle_anim.c b/src/battle_anim.c index b52ef0592..e6152a7cf 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -2052,13 +2052,13 @@ const struct BattleAnimBackground gBattleAnimBackgroundTable[] = [BG_SOLARBEAM_CONTESTS] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_Solarbeam, gBattleAnimBgTilemap_ImpactContests}, //new bgs [BG_MAGMA_STORM] = {gBattleAnimBgImage_InAir, gBattleAnimBgPalette_MagmaStorm, gBattleAnimBgTilemap_InAir}, - [BG_GIGA_IMPACT_OPPONENT] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_ImpactOpponent}, - [BG_GIGA_IMPACT_PLAYER] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_ImpactPlayer}, - [BG_GIGA_IMPACT_CONTEST] = {gBattleAnimBgImage_Impact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_ImpactContests}, + [BG_GIGA_IMPACT_OPPONENT] = {gBattleAnimBgImage_GigaImpact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_GigaImpactOpponent}, + [BG_GIGA_IMPACT_PLAYER] = {gBattleAnimBgImage_GigaImpact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_GigaImpactPlayer}, + [BG_GIGA_IMPACT_CONTEST] = {gBattleAnimBgImage_GigaImpact, gBattleAnimBgPalette_GigaImpact, gBattleAnimBgTilemap_GigaImpactContest}, [BG_TRICK_ROOM] = {gBattleAnimBgImage_TrickRoom, gBattleAnimBgPalette_TrickRoom, gBattleAnimBgTilemap_TrickRoom}, [BG_ROCK_WRECKER] = {gBattleAnimBgImage_Hurricane, gBattleAnimBgPalette_RockWrecker, gBattleAnimBgTilemap_Hurricane}, - [BG_SPACIAL_REND_ON_OPPONENT] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_SpacialRendOpponent}, - [BG_SPACIAL_REND_ON_PLAYER] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_SpacialRendPlayer}, + [BG_SPACIAL_REND_ON_OPPONENT] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_GigaImpactOpponent}, + [BG_SPACIAL_REND_ON_PLAYER] = {gBattleAnimBgImage_SpacialRend, gBattleAnimBgPalette_SpacialRend, gBattleAnimBgTilemap_GigaImpactPlayer}, [BG_DARK_VOID] = {gBattleAnimBgImage_Waterfall, gBattleAnimBgPalette_DarkVoid, gBattleAnimBgTilemap_DarkVoid}, [BG_WATER] = {gBattleAnimBgImage_HydroPump, gBattleAnimBgPalette_HydroPump, gBattleAnimBgTilemap_HydroPump}, [BG_NIGHTMARE] = {gBattleAnimBgImage_Nightmare, gBattleAnimBgPalette_Nightmare, gBattleAnimBgTilemap_Nightmare}, diff --git a/src/battle_debug.c b/src/battle_debug.c index c967cfe00..a10e60412 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -1924,12 +1924,20 @@ static const u8 sText_HoldEffectPsychicPower[] = _("Psychic Power"); static const u8 sText_HoldEffectFirePower[] = _("Fire Power"); static const u8 sText_HoldEffectDragonPower[] = _("Dragon Power"); static const u8 sText_HoldEffectNormalPower[] = _("Normal Power"); -static const u8 sText_HoldEffectUpGrade[] = _("Up Grade"); +#ifdef ITEM_EXPANSION +static const u8 sText_HoldEffectUpgrade[] = _("Upgrade"); +#else +static const u8 sText_HoldEffectUpgrade[] = _("Up Grade"); +#endif static const u8 sText_HoldEffectShellBell[] = _("Shell Bell"); static const u8 sText_HoldEffectLuckyPunch[] = _("Lucky Punch"); static const u8 sText_HoldEffectMetalPowder[] = _("Metal Powder"); static const u8 sText_HoldEffectThickClub[] = _("Thick Club"); -static const u8 sText_HoldEffectStick[] = _("Stick"); +#ifdef ITEM_EXPANSION +static const u8 sText_HoldEffectLeek[] = _("Leek"); +#else +static const u8 sText_HoldEffectLeek[] = _("Stick"); +#endif static const u8 sText_HoldEffectChoiceScarf[] = _("Choice Scarf"); static const u8 sText_HoldEffectChoiceSpecs[] = _("Choice Specs"); static const u8 sText_HoldEffectDampRock[] = _("Damp Rock"); @@ -2064,12 +2072,12 @@ static const u8 *const sHoldEffectNames[] = [HOLD_EFFECT_FIRE_POWER] = sText_HoldEffectFirePower, [HOLD_EFFECT_DRAGON_POWER] = sText_HoldEffectDragonPower, [HOLD_EFFECT_NORMAL_POWER] = sText_HoldEffectNormalPower, - [HOLD_EFFECT_UP_GRADE] = sText_HoldEffectUpGrade, + [HOLD_EFFECT_UPGRADE] = sText_HoldEffectUpgrade, [HOLD_EFFECT_SHELL_BELL] = sText_HoldEffectShellBell, [HOLD_EFFECT_LUCKY_PUNCH] = sText_HoldEffectLuckyPunch, [HOLD_EFFECT_METAL_POWDER] = sText_HoldEffectMetalPowder, [HOLD_EFFECT_THICK_CLUB] = sText_HoldEffectThickClub, - [HOLD_EFFECT_STICK] = sText_HoldEffectStick, + [HOLD_EFFECT_LEEK] = sText_HoldEffectLeek, [HOLD_EFFECT_CHOICE_SCARF] = sText_HoldEffectChoiceScarf, [HOLD_EFFECT_CHOICE_SPECS] = sText_HoldEffectChoiceSpecs, [HOLD_EFFECT_DAMP_ROCK] = sText_HoldEffectDampRock, diff --git a/src/battle_main.c b/src/battle_main.c index 9ffaab746..292c0fdc3 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3549,7 +3549,11 @@ static void TryDoEventsBeforeFirstTurn(void) return; } } - + + // Check neutralizing gas + if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) + return; + // Check all switch in abilities happening from the fastest mon to slowest. while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount) { diff --git a/src/battle_message.c b/src/battle_message.c index 30af20a78..d64d02f90 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -629,7 +629,7 @@ static const u8 sText_TerrainBecomesGrassy[] = _("Grass grew to cover\nthe battl static const u8 sText_TerrainBecomesElectric[] = _("An electric current runs across\nthe battlefield!"); static const u8 sText_TerrainBecomesPsychic[] = _("The battlefield got weird!"); static const u8 sText_TargetElectrified[] = _("The {B_DEF_NAME_WITH_PREFIX}'s moves\nhave been electrified!"); -static const u8 sText_AssaultVestDoesntAllow[] = _("The effects of the {B_LAST_ITEM} prevent status\nmoves from being used!\p"); +static const u8 sText_AssaultVestDoesntAllow[] = _("{B_LAST_ITEM}'s effects prevent\nstatus moves from being used!\p"); static const u8 sText_GravityPreventsUsage[] = _("{B_ATK_NAME_WITH_PREFIX} can't use {B_CURRENT_MOVE}\nbecause of gravity!\p"); static const u8 sText_HealBlockPreventsUsage[] = _("{B_ATK_NAME_WITH_PREFIX} was\nprevented from healing!\p"); static const u8 sText_MegaEvoReacting[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_LAST_ITEM} is \nreacting to {B_ATK_TRAINER_NAME}'s Mega Ring!"); @@ -733,9 +733,13 @@ static const u8 sText_CantEscapeDueToUsedMove[] = _("{B_ATK_NAME_WITH_PREFIX} ca static const u8 sText_PkmnBecameWeakerToFire[] = _("{B_DEF_NAME_WITH_PREFIX} became\nweaker to fire!"); static const u8 sText_PkmnAboutToBeAttackedByItsItem[] = _("{B_DEF_NAME_WITH_PREFIX} is about\nto be attacked by its {B_BUFF1}!"); static const u8 sText_CantEscapeBecauseOfCurrentMove[] = _("{B_DEF_NAME_WITH_PREFIX} can no longer escape\nbecause of {B_CURRENT_MOVE}!"); +static const u8 sText_NeutralizingGasEnters[] = _("Neutralizing Gas filled the area!"); +static const u8 sText_NeutralizingGasOver[] = _("The effects of Neutralizing\nGas wore off!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_NEUTRALIZINGGASOVER - 12] = sText_NeutralizingGasOver, + [STRINGID_NEUTRALIZINGGASENTERS - 12] = sText_NeutralizingGasEnters, [STRINGID_BATTLERTYPECHANGEDTO - 12] = sText_BattlerTypeChangedTo, [STRINGID_PASTELVEILENTERS - 12] = sText_PastelVeilEnters, [STRINGID_PASTELVEILPROTECTED -12] = sText_PastelVeilProtected, @@ -1392,6 +1396,7 @@ const u16 gSwitchInAbilityStringIds[] = [B_MSG_SWITCHIN_ASONE] = STRINGID_ASONEENTERS, [B_MSG_SWITCHIN_CURIOUS_MEDICINE] = STRINGID_CURIOUSMEDICINEENTERS, [B_MSG_SWITCHIN_PASTEL_VEIL] = STRINGID_PASTELVEILENTERS, + [B_MSG_SWITCHIN_NEUTRALIZING_GAS] = STRINGID_NEUTRALIZINGGASENTERS, }; const u16 gMissStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 403d08748..63bdd5339 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1367,47 +1367,6 @@ static const u8 sBattlePalaceNatureToFlavorTextId[NUM_NATURES] = [NATURE_QUIRKY] = B_MSG_EAGER_FOR_MORE, }; -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) - 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].obstructed && !IS_MOVE_STATUS(move)) - return TRUE; - else if (gProtectStructs[battlerId].spikyShielded) - return TRUE; - else if (gProtectStructs[battlerId].kingsShielded && gBattleMoves[move].power != 0) - return TRUE; - else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD - && GetChosenMovePriority(gBattlerAttacker) > 0) - return TRUE; - else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD - && IS_MOVE_STATUS(move)) - return TRUE; - else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK - && !IS_MOVE_STATUS(move)) - return TRUE; - else - return FALSE; -} - static bool32 NoTargetPresent(u32 move) { if (!IsBattlerAlive(gBattlerTarget)) @@ -1975,11 +1934,13 @@ static void Cmd_ppreduce(void) static const u8 sCriticalHitChance[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5 #endif // B_CRIT_CHANCE +#define BENEFITS_FROM_LEEK(battler, holdEffect)((holdEffect == HOLD_EFFECT_LEEK) && (GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_FARFETCHD || gBattleMons[battler].species == SPECIES_SIRFETCHD)) s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility) { s32 critChance = 0; u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); u32 abilityDef = GetBattlerAbility(gBattlerTarget); + u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); if (gSideStatuses[battlerDef] & SIDE_STATUS_LUCKY_CHANT || gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT) @@ -1995,19 +1956,21 @@ 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) - || move == MOVE_SURGING_STRIKES) + || move == MOVE_SURGING_STRIKES + #if B_LEEK_ALWAYS_CRIT >= GEN_6 + || ((gBattleMoves[gCurrentMove].flags & FLAG_HIGH_CRIT) && BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk)) + #endif + ) { critChance = -2; } else { - u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - critChance = 2 * ((gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0) + ((gBattleMoves[gCurrentMove].flags & FLAG_HIGH_CRIT) != 0) + (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS) + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) - + 2 * (holdEffectAtk == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD) + + 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) + (abilityAtk == ABILITY_SUPER_LUCK); if (critChance >= ARRAY_COUNT(sCriticalHitChance)) @@ -2016,6 +1979,7 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi return critChance; } +#undef BENEFITS_FROM_LEEK s8 GetInverseCritChance(u8 battlerAtk, u8 battlerDef, u32 move) { @@ -3301,7 +3265,11 @@ void SetMoveEffect(bool32 primary, u32 certain) RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } else if (gBattleMons[gBattlerAttacker].item != 0 + #ifdef ITEM_EXPANSION + || gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY_E_READER + #else || gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY + #endif || gBattleMons[gBattlerTarget].item == 0) { gBattlescriptCurrInstr++; @@ -6363,8 +6331,17 @@ static void Cmd_switchineffects(void) gHitMarker &= ~(HITMARKER_FAINTED(gActiveBattler)); gSpecialStatuses[gActiveBattler].flag40 = 0; - - if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES_DAMAGED) + + // Neutralizing Gas announces itself before hazards + if (gBattleMons[gActiveBattler].ability == ABILITY_NEUTRALIZING_GAS && gSpecialStatuses[gActiveBattler].announceNeutralizingGas == 0) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; + gSpecialStatuses[gActiveBattler].announceNeutralizingGas = TRUE; + gBattlerAbility = gActiveBattler; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SwitchInAbilityMsgRet; + } + else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES) && GetBattlerAbility(gActiveBattler) != ABILITY_MAGIC_GUARD && IsBattlerAffectedByHazards(gActiveBattler, FALSE) @@ -6438,7 +6415,7 @@ static void Cmd_switchineffects(void) { // There is a hack here to ensure the truant counter will be 0 when the battler's next turn starts. // The truant counter is not updated in the case where a mon switches in after a lost judgement in the battle arena. - if (gBattleMons[gActiveBattler].ability == ABILITY_TRUANT + if (GetBattlerAbility(gActiveBattler) == ABILITY_TRUANT && gCurrentActionFuncId != B_ACTION_USE_MOVE && !gDisableStructs[gActiveBattler].truantSwitchInHack) gDisableStructs[gActiveBattler].truantCounter = 1; @@ -7629,7 +7606,7 @@ u32 IsLeafGuardProtected(u32 battler) bool32 IsShieldsDownProtected(u32 battler) { - return (gBattleMons[battler].ability == ABILITY_SHIELDS_DOWN + return (GetBattlerAbility(battler) == ABILITY_SHIELDS_DOWN && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < GetFormIdFromFormSpeciesId(SPECIES_MINIOR_CORE_RED)); // Minior is not in core form } @@ -8097,6 +8074,7 @@ static void Cmd_various(void) break; case VARIOUS_SWITCHIN_ABILITIES: gBattlescriptCurrInstr += 3; + AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, gActiveBattler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gActiveBattler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_INTIMIDATE2, gActiveBattler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_TRACE2, gActiveBattler, 0, 0, 0); @@ -8277,6 +8255,9 @@ static void Cmd_various(void) } else { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + gBattleMons[gBattlerTarget].ability = ABILITY_SIMPLE; gBattlescriptCurrInstr += 7; } @@ -9153,11 +9134,11 @@ static void Cmd_various(void) for (i = 0; i < gBattlersCount; i++) { - if (((GetBattlerAbility(i) == ABILITY_DESOLATE_LAND && gBattleWeather & WEATHER_SUN_PRIMAL) - || (GetBattlerAbility(i) == ABILITY_PRIMORDIAL_SEA && gBattleWeather & WEATHER_RAIN_PRIMAL) - || (GetBattlerAbility(i) == ABILITY_DELTA_STREAM && gBattleWeather & WEATHER_STRONG_WINDS)) - && IsBattlerAlive(i) - && !(gStatuses3[i] & STATUS3_GASTRO_ACID)) + u32 ability = GetBattlerAbility(i); + if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & WEATHER_SUN_PRIMAL) + || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & WEATHER_RAIN_PRIMAL) + || (ability == ABILITY_DELTA_STREAM && gBattleWeather & WEATHER_STRONG_WINDS)) + && IsBattlerAlive(i)) shouldNotClear = TRUE; } if (gBattleWeather & WEATHER_SUN_PRIMAL && !shouldNotClear) @@ -9180,6 +9161,15 @@ static void Cmd_various(void) } break; } + case VARIOUS_TRY_END_NEUTRALIZING_GAS: + if (gSpecialStatuses[gActiveBattler].neutralizingGasRemoved) + { + gSpecialStatuses[gActiveBattler].neutralizingGasRemoved = FALSE; + BattleScriptPush(gBattlescriptCurrInstr + 3); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + return; + } + break; case VARIOUS_GET_ROTOTILLER_TARGETS: // Gets the battlers to be affected by rototiller. If there are none, print 'But it failed!' { @@ -11604,11 +11594,11 @@ static void Cmd_healpartystatus(void) u16 ability; if (gBattlerPartyIndexes[gBattlerAttacker] == i) - ability = gBattleMons[gBattlerAttacker].ability; + ability = GetBattlerAbility(gBattlerAttacker); else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattlerPartyIndexes[gActiveBattler] == i && !(gAbsentBattlerFlags & gBitTable[gActiveBattler])) - ability = gBattleMons[gActiveBattler].ability; + ability = GetBattlerAbility(gActiveBattler); else ability = GetAbilityBySpecies(species, abilityNum); @@ -12530,12 +12520,13 @@ static void Cmd_trywish(void) break; case 1: // heal effect PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerTarget, gWishFutureKnock.wishMonId[gBattlerTarget]) - - gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 2; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; + #if B_WISH_HP_SOURCE >= GEN_5 + gBattleMoveDamage = max(1, gBattleMons[gWishFutureKnock.wishMonId[gBattlerTarget]].maxHP / 2); + #else + gBattleMoveDamage = max(1, gBattleMons[gBattlerTarget].maxHP / 2); + #endif + gBattleMoveDamage *= -1; - if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else @@ -12568,6 +12559,9 @@ static void Cmd_setgastroacid(void) } else { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID; gBattlescriptCurrInstr += 5; } @@ -12848,25 +12842,33 @@ static void Cmd_trygetintimidatetarget(void) static void Cmd_switchoutabilities(void) { gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - - switch (GetBattlerAbility(gActiveBattler)) + if (gBattleMons[gActiveBattler].ability == ABILITY_NEUTRALIZING_GAS) { - case ABILITY_NATURAL_CURE: - gBattleMons[gActiveBattler].status1 = 0; - BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, gBitTable[*(gBattleStruct->field_58 + gActiveBattler)], 4, &gBattleMons[gActiveBattler].status1); - MarkBattlerForControllerExec(gActiveBattler); - break; - case ABILITY_REGENERATOR: - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 3; - gBattleMoveDamage += gBattleMons[gActiveBattler].hp; - if (gBattleMoveDamage > gBattleMons[gActiveBattler].maxHP) - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP; - BtlController_EmitSetMonData(0, REQUEST_HP_BATTLE, gBitTable[*(gBattleStruct->field_58 + gActiveBattler)], 2, &gBattleMoveDamage); - MarkBattlerForControllerExec(gActiveBattler); - break; + gBattleMons[gActiveBattler].ability = ABILITY_NONE; + BattleScriptPush(gBattlescriptCurrInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + } + else + { + switch (GetBattlerAbility(gActiveBattler)) + { + case ABILITY_NATURAL_CURE: + gBattleMons[gActiveBattler].status1 = 0; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, gBitTable[*(gBattleStruct->field_58 + gActiveBattler)], 4, &gBattleMons[gActiveBattler].status1); + MarkBattlerForControllerExec(gActiveBattler); + break; + case ABILITY_REGENERATOR: + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 3; + gBattleMoveDamage += gBattleMons[gActiveBattler].hp; + if (gBattleMoveDamage > gBattleMons[gActiveBattler].maxHP) + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP; + BtlController_EmitSetMonData(0, REQUEST_HP_BATTLE, gBitTable[*(gBattleStruct->field_58 + gActiveBattler)], 2, &gBattleMoveDamage); + MarkBattlerForControllerExec(gActiveBattler); + break; + } + + gBattlescriptCurrInstr += 2; } - - gBattlescriptCurrInstr += 2; } static void Cmd_jumpifhasnohp(void) @@ -13361,7 +13363,7 @@ static void Cmd_handleballthrow(void) u8 catchRate; gLastThrownBall = gLastUsedItem; - if (gLastUsedItem == ITEM_SAFARI_BALL) + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) catchRate = gBattleStruct->safariCatchFactor * 1275 / 100; else catchRate = gBaseStats[gBattleMons[gBattlerTarget].species].catchRate; diff --git a/src/battle_util.c b/src/battle_util.c index ee17d56ba..1b3adc43d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -335,8 +335,8 @@ void HandleAction_UseMove(void) else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gSideTimers[side].followmeTimer == 0 && (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER) - && ((gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) + && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) + || (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { side = GetBattlerSide(gBattlerAttacker); for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) @@ -405,9 +405,9 @@ void HandleAction_UseMove(void) { gActiveBattler = gBattlerByTurnOrder[var]; RecordAbilityBattle(gActiveBattler, gBattleMons[gActiveBattler].ability); - if (gBattleMons[gActiveBattler].ability == ABILITY_LIGHTNING_ROD) + if (GetBattlerAbility(gActiveBattler) == ABILITY_LIGHTNING_ROD) gSpecialStatuses[gActiveBattler].lightningRodRedirected = TRUE; - else if (gBattleMons[gActiveBattler].ability == ABILITY_STORM_DRAIN) + else if (GetBattlerAbility(gActiveBattler) == ABILITY_STORM_DRAIN) gSpecialStatuses[gActiveBattler].stormDrainRedirected = TRUE; gBattlerTarget = gActiveBattler; } @@ -645,7 +645,7 @@ bool8 TryRunFromBattle(u8 battler) effect++; } #endif - else if (gBattleMons[battler].ability == ABILITY_RUN_AWAY) + else if (GetBattlerAbility(battler) == ABILITY_RUN_AWAY) { if (InBattlePyramid()) { @@ -1780,7 +1780,7 @@ u8 TrySetCantSelectMoveBattleScript(void) limitations++; } } - else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[move].power == 0) + else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[move].power == 0 && move != MOVE_ME_FIRST) { gCurrentMove = move; gLastUsedItem = gBattleMons[gActiveBattler].item; @@ -1852,7 +1852,7 @@ u8 CheckMoveLimitations(u8 battlerId, u8 unusableMoves, u8 check) unusableMoves |= gBitTable[i]; else if (HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != gBattleMons[battlerId].moves[i]) unusableMoves |= gBitTable[i]; - else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[gBattleMons[battlerId].moves[i]].power == 0) + else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && gBattleMoves[gBattleMons[battlerId].moves[i]].power == 0 && gBattleMons[battlerId].moves[i] != MOVE_ME_FIRST) unusableMoves |= gBitTable[i]; else if (IsGravityPreventingMove(gBattleMons[battlerId].moves[i])) unusableMoves |= gBitTable[i]; @@ -2745,7 +2745,7 @@ u8 DoBattlerEndTurnEffects(void) for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) { if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) - && gBattleMons[gBattlerAttacker].ability != ABILITY_SOUNDPROOF) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF) { gBattleMons[gBattlerAttacker].status1 &= ~(STATUS1_SLEEP); gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_NIGHTMARE); @@ -3331,7 +3331,7 @@ u8 AtkCanceller_UnableToUseMove(void) gBattleStruct->atkCancellerTracker++; break; case CANCELLER_TRUANT: // truant - if (gBattleMons[gBattlerAttacker].ability == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) { CancelMultiTurnMoves(gBattlerAttacker); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; @@ -3861,7 +3861,7 @@ u8 TryWeatherFormChange(u8 battler) if (gBattleMons[battler].species == SPECIES_CASTFORM) { - if (gBattleMons[battler].ability != ABILITY_FORECAST || gBattleMons[battler].hp == 0) + if (GetBattlerAbility(battler) != ABILITY_FORECAST || gBattleMons[battler].hp == 0) { ret = 0; } @@ -3897,11 +3897,11 @@ u8 TryWeatherFormChange(u8 battler) } else if (gBattleMons[battler].species == SPECIES_CHERRIM) { - if (gBattleMons[battler].ability != ABILITY_FLOWER_GIFT || gBattleMons[battler].hp == 0) + if (GetBattlerAbility(battler) != ABILITY_FLOWER_GIFT || gBattleMons[battler].hp == 0) ret = 0; else if (gBattleMonForms[battler] == 0 && weatherEffect && holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA && gBattleWeather & WEATHER_SUN_ANY) ret = 2; - else if (gBattleMonForms[battler] != 0 && (!weatherEffect || holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA || !(gBattleWeather & WEATHER_SUN_ANY))) + else if (gBattleMonForms[battler] != 0 && (!weatherEffect || holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA || !(gBattleWeather & WEATHER_SUN_ANY))) ret = 1; } @@ -3987,7 +3987,7 @@ static bool32 ShouldChangeFormHpBased(u32 battler) for (i = 0; i < ARRAY_COUNT(forms); i++) { - if (gBattleMons[battler].ability == forms[i][0]) + if (GetBattlerAbility(battler) == forms[i][0]) { if (gBattleMons[battler].species == forms[i][2] && gBattleMons[battler].hp > gBattleMons[battler].maxHP / forms[i][3]) @@ -5482,7 +5482,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITYEFFECT_IMMUNITY: // 5 for (battler = 0; battler < gBattlersCount; battler++) { - switch (gBattleMons[battler].ability) + switch (GetBattlerAbility(battler)) { case ABILITY_IMMUNITY: if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON | STATUS1_TOXIC_COUNTER)) @@ -5572,7 +5572,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITYEFFECT_FORECAST: // 6 for (battler = 0; battler < gBattlersCount; battler++) { - if (gBattleMons[battler].ability == ABILITY_FORECAST || gBattleMons[battler].ability == ABILITY_FLOWER_GIFT) + if (GetBattlerAbility(battler) == ABILITY_FORECAST || GetBattlerAbility(battler) == ABILITY_FLOWER_GIFT) { effect = TryWeatherFormChange(battler); if (effect) @@ -5633,7 +5633,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITYEFFECT_INTIMIDATE2: for (i = 0; i < gBattlersCount; i++) { - if (gBattleMons[i].ability == ABILITY_INTIMIDATE && gBattleResources->flags->flags[i] & RESOURCE_FLAG_INTIMIDATED) + if (GetBattlerAbility(i) == ABILITY_INTIMIDATE && gBattleResources->flags->flags[i] & RESOURCE_FLAG_INTIMIDATED) { gLastUsedAbility = ABILITY_INTIMIDATE; gBattleResources->flags->flags[i] &= ~(RESOURCE_FLAG_INTIMIDATED); @@ -5700,6 +5700,23 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } } break; + case ABILITYEFFECT_NEUTRALIZINGGAS: + // Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gBattleResources->flags->flags[i] & RESOURCE_FLAG_NEUTRALIZING_GAS)) + { + gBattleResources->flags->flags[i] |= RESOURCE_FLAG_NEUTRALIZING_GAS; + gBattlerAbility = i; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; + BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); + effect++; + } + + if (effect) + break; + } + break; } if (effect && gLastUsedAbility != 0xFF) @@ -5710,11 +5727,51 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move return effect; } +bool32 IsNeutralizingGasBannedAbility(u32 ability) +{ + switch (ability) + { + case ABILITY_MULTITYPE: + case ABILITY_ZEN_MODE: + case ABILITY_STANCE_CHANGE: + case ABILITY_POWER_CONSTRUCT: + case ABILITY_SCHOOLING: + case ABILITY_RKS_SYSTEM: + case ABILITY_SHIELDS_DOWN: + case ABILITY_COMATOSE: + case ABILITY_DISGUISE: + case ABILITY_GULP_MISSILE: + case ABILITY_ICE_FACE: + case ABILITY_AS_ONE_ICE_RIDER: + case ABILITY_AS_ONE_SHADOW_RIDER: + return TRUE; + default: + return FALSE; + } +} + +bool32 IsNeutralizingGasOnField(void) +{ + u32 i; + + for (i = 0; i < gBattlersCount; i++) + { + if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gStatuses3[i] & STATUS3_GASTRO_ACID)) + return TRUE; + } + + return FALSE; +} + u32 GetBattlerAbility(u8 battlerId) { if (gStatuses3[battlerId] & STATUS3_GASTRO_ACID) return ABILITY_NONE; - else if ((((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER + + if (IsNeutralizingGasOnField() && !IsNeutralizingGasBannedAbility(gBattleMons[battlerId].ability)) + return ABILITY_NONE; + + if ((((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER || gBattleMons[gBattlerAttacker].ability == ABILITY_TERAVOLT || gBattleMons[gBattlerAttacker].ability == ABILITY_TURBOBLAZE) && !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID)) @@ -5724,8 +5781,8 @@ u32 GetBattlerAbility(u8 battlerId) && gActionsByTurnOrder[gBattlerByTurnOrder[gBattlerAttacker]] == B_ACTION_USE_MOVE && gCurrentTurnActionNumber < gBattlersCount) return ABILITY_NONE; - else - return gBattleMons[battlerId].ability; + + return gBattleMons[battlerId].ability; } u32 IsAbilityOnSide(u32 battlerId, u32 ability) @@ -5777,7 +5834,7 @@ u32 IsAbilityPreventingEscape(u32 battlerId) return 0; #endif #if B_SHADOW_TAG_ESCAPE >= GEN_4 - if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && gBattleMons[battlerId].ability != ABILITY_SHADOW_TAG) + if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && GetBattlerAbility(battlerId) != ABILITY_SHADOW_TAG) #else if (id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) #endif @@ -7328,7 +7385,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) targetBattler = SetRandomTarget(gBattlerAttacker); if (gBattleMoves[move].type == TYPE_ELECTRIC && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD) - && gBattleMons[targetBattler].ability != ABILITY_LIGHTNING_ROD) + && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) { targetBattler ^= BIT_FLANK; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); @@ -7336,7 +7393,7 @@ u32 GetMoveTarget(u16 move, u8 setTarget) } else if (gBattleMoves[move].type == TYPE_WATER && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_STORM_DRAIN) - && gBattleMons[targetBattler].ability != ABILITY_STORM_DRAIN) + && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) { targetBattler ^= BIT_FLANK; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); @@ -7514,7 +7571,7 @@ u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating) return HOLD_EFFECT_NONE; if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) return HOLD_EFFECT_NONE; - if (gBattleMons[battlerId].ability == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID)) + if (GetBattlerAbility(battlerId) == ABILITY_KLUTZ) return HOLD_EFFECT_NONE; } @@ -7559,6 +7616,48 @@ bool32 IsMoveMakingContact(u16 move, u8 battlerAtk) } } +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) + 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].obstructed && !IS_MOVE_STATUS(move)) + return TRUE; + else if (gProtectStructs[battlerId].spikyShielded) + return TRUE; + else if (gProtectStructs[battlerId].kingsShielded && gBattleMoves[move].power != 0) + return TRUE; + else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD + && GetChosenMovePriority(gBattlerAttacker) > 0) + return TRUE; + else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD + && IS_MOVE_STATUS(move)) + return TRUE; + else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK + && !IS_MOVE_STATUS(move)) + return TRUE; + else + return FALSE; +} + + bool32 IsBattlerGrounded(u8 battlerId) { if (GetBattlerHoldEffect(battlerId, TRUE) == HOLD_EFFECT_IRON_BALL) @@ -8146,7 +8245,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe if (IsAbilityOnField(ABILITY_AURA_BREAK)) MulModifier(&modifier, UQ_4_12(0.75)); else - MulModifier(&modifier, UQ_4_12(1.25)); + MulModifier(&modifier, UQ_4_12(1.33)); } // attacker partner's abilities @@ -8307,8 +8406,11 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe MulModifier(&modifier, UQ_4_12(0.5)); break; case EFFECT_KNOCK_OFF: - if (gBattleMons[battlerDef].item != ITEM_NONE && GetBattlerAbility(battlerDef) != ABILITY_STICKY_HOLD) + #if B_KNOCK_OFF_DMG >= GEN_6 + if (gBattleMons[battlerDef].item != ITEM_NONE + && CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item)) MulModifier(&modifier, UQ_4_12(1.5)); + #endif break; } @@ -8723,7 +8825,9 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move if (((gSideStatuses[defSide] & SIDE_STATUS_REFLECT && IS_MOVE_PHYSICAL(move)) || (gSideStatuses[defSide] & SIDE_STATUS_LIGHTSCREEN && IS_MOVE_SPECIAL(move)) || (gSideStatuses[defSide] & SIDE_STATUS_AURORA_VEIL)) - && abilityAtk != ABILITY_INFILTRATOR) + && abilityAtk != ABILITY_INFILTRATOR + && !(isCrit) + && !gProtectStructs[gBattlerAttacker].confusionSelfDmg) { if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) MulModifier(&finalModifier, UQ_4_12(0.66)); @@ -8904,9 +9008,6 @@ static void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, u8 batt if (moveType == TYPE_FIRE && gDisableStructs[battlerDef].tarShot) mod = UQ_4_12(2.0); - if (gProtectStructs[battlerDef].kingsShielded && gBattleMoves[move].effect != EFFECT_FEINT) - mod = UQ_4_12(1.0); - // WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_STRONG_WINDS) { @@ -9130,9 +9231,9 @@ bool32 CanMegaEvolve(u8 battlerId) struct MegaEvolutionData *mega = &(((struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]))->mega); #ifdef ITEM_EXPANSION - // Check if Player has a Mega Bracelet + // Check if Player has a Mega Ring if ((GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT)) - && !CheckBagHasItem(ITEM_MEGA_BRACELET, 1)) + && !CheckBagHasItem(ITEM_MEGA_RING, 1)) return FALSE; #endif diff --git a/src/battle_util2.c b/src/battle_util2.c index d15700706..0af19de27 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -142,7 +142,7 @@ u32 sub_805725C(u8 battlerId) { u32 toSub; - if (gBattleMons[battlerId].ability == ABILITY_EARLY_BIRD) + if (GetBattlerAbility(battlerId) == ABILITY_EARLY_BIRD) toSub = 2; else toSub = 1; diff --git a/src/data/items.h b/src/data/items.h index ef5c8825d..7e62558aa 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -2680,7 +2680,7 @@ const struct Item gItems[] = .name = _("UP-GRADE"), .itemId = ITEM_UP_GRADE, .price = 2100, - .holdEffect = HOLD_EFFECT_UP_GRADE, + .holdEffect = HOLD_EFFECT_UPGRADE, .description = sUpGradeDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2767,7 +2767,7 @@ const struct Item gItems[] = .name = _("STICK"), .itemId = ITEM_STICK, .price = 200, - .holdEffect = HOLD_EFFECT_STICK, + .holdEffect = HOLD_EFFECT_LEEK, .description = sStickDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, diff --git a/src/graphics.c b/src/graphics.c index 153d75c71..1621f9d5b 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1395,7 +1395,6 @@ const u32 gBattleAnimBgPalette_Solarbeam[] = INCBIN_U32("graphics/battle_anims/b const u32 gBattleAnimBgPalette_MagmaStorm[] = INCBIN_U32("graphics/battle_anims/backgrounds/magma_storm.gbapal.lz"); //new battle bgs -const u32 gBattleAnimBgPalette_GigaImpact[] = INCBIN_U32("graphics/battle_anims/backgrounds/giga_impact.gbapal.lz"); const u32 gBattleAnimBgImage_Hurricane[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/hurricane.4bpp.lz"); const u32 gBattleAnimBgPalette_Hurricane[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/hurricane.gbapal.lz"); @@ -1403,10 +1402,14 @@ const u32 gBattleAnimBgTilemap_Hurricane[] = INCBIN_U32("graphics/battle_anims/b const u32 gBattleAnimBgPalette_RockWrecker[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/rock_wrecker.gbapal.lz"); +const u32 gBattleAnimBgTilemap_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.bin.lz"); +const u32 gBattleAnimBgTilemap_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin.lz"); +const u32 gBattleAnimBgTilemap_GigaImpactContest[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_contest.bin.lz"); +const u32 gBattleAnimBgImage_GigaImpact[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact.4bpp.lz"); +const u32 gBattleAnimBgPalette_GigaImpact[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact.gbapal.lz"); + const u32 gBattleAnimBgImage_SpacialRend[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend.4bpp.lz"); const u32 gBattleAnimBgPalette_SpacialRend[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend.gbapal.lz"); -const u32 gBattleAnimBgTilemap_SpacialRendOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend_opponent.bin.lz"); -const u32 gBattleAnimBgTilemap_SpacialRendPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/spacial_rend_player.bin.lz"); const u32 gBattleAnimBgPalette_SludgeWave[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/sludge_wave.gbapal.lz"); @@ -1450,14 +1453,6 @@ const u32 gBattleAnimBgTilemap_FocusBlast[] = INCBIN_U32("graphics/battle_anims/ const u32 gBattleAnimBgPalette_GarbageFalls[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/garbage_falls.gbapal.lz"); -const u32 gBattleAnimBgImage_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.4bpp.lz"); -const u32 gBattleAnimBgPalette_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.gbapal.lz"); -const u32 gBattleAnimBgTilemap_GigaImpactOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_opponent.bin.lz"); - -const u32 gBattleAnimBgImage_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.4bpp.lz"); -const u32 gBattleAnimBgPalette_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.gbapal.lz"); -const u32 gBattleAnimBgTilemap_GigaImpactPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/giga_impact_player.bin.lz"); - const u32 gBattleAnimBgImage_GrassyTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/grassy_terrain.4bpp.lz"); const u32 gBattleAnimBgPalette_GrassyTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/grassy_terrain.gbapal.lz"); const u32 gBattleAnimBgTilemap_GrassyTerrain[] = INCBIN_U32("graphics/battle_anims/backgrounds/new/grassy_terrain.bin.lz");