diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index a15dd459f..6ba63f916 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 ee859f0e0..e9d019e43 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2187,6 +2187,7 @@ BattleScript_EffectSimpleBeam: trytoclearprimalweather printstring STRINGID_EMPTYSTRING3 waitmessage 1 + tryendneutralizinggas BS_TARGET goto BattleScript_MoveEnd BattleScript_EffectSuckerPunch: @@ -2409,6 +2410,7 @@ BattleScript_EffectGastroAcid: trytoclearprimalweather printstring STRINGID_EMPTYSTRING3 waitmessage 1 + tryendneutralizinggas BS_TARGET goto BattleScript_MoveEnd BattleScript_EffectToxicSpikes: @@ -8378,6 +8380,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 @@ -9231,3 +9239,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 f1262b128..b587e482d 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 { @@ -184,6 +185,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 41d4ee91d..415eaa6bb 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,5 +414,6 @@ 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[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_util.h b/include/battle_util.h index fb74610d0..b1a2a1534 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 aaf02a37f..6f4e283ca 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -114,6 +114,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 // Type settings #define B_GHOSTS_ESCAPE GEN_7 // In Gen6+, abilities like Shadow Tag or moves like Mean Look fail on Ghost-type Pokémon. They can also escape any Wild Battle. @@ -152,6 +153,8 @@ #define B_MEMENTO_FAIL GEN_7 // In Gen4+, Memento fails if there is no target or if the target is protected or behind substitute. But not if Atk/Sp. Atk are at -6. #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. @@ -181,6 +184,7 @@ #define B_LURE_BALL_MODIFIER GEN_7 // In Gen7+, Lure Ball's catch multiplier is x5 instead of x3. #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. // 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 34fa1d370..bd16f741b 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -207,6 +207,7 @@ #define VARIOUS_CHECK_POLTERGEIST 134 #define VARIOUS_SET_OCTOLOCK 135 #define VARIOUS_CUT_1_3_HP_RAISE_STATS 136 +#define VARIOUS_TRY_END_NEUTRALIZING_GAS 137 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 @@ -225,6 +226,7 @@ // Cmd_statbuffchange #define STAT_BUFF_ALLOW_PTR (1 << 0) // If set, allow use of jumpptr. Set in every use of statbuffchange #define STAT_BUFF_NOT_PROTECT_AFFECTED (1 << 5) +#define STAT_BUFF_UPDATE_MOVE_EFFECT (1 << 6) // stat change flags for Cmd_playstatchangeanimation #define STAT_CHANGE_NEGATIVE (1 << 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 3e51b0dc4..0973ba8ef 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 499969ec3..93bf3ec91 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1121,20 +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; - - // AI has no knowledge of opponent, so it guesses which 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) { u16 abilityGuess = ABILITY_NONE; @@ -1145,6 +1149,7 @@ s32 AI_GetAbility(u32 battlerId) return abilityGuess; } + return ABILITY_NONE; // Unknown. } 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 0b96794a6..5277ade1e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3548,7 +3548,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 24a758153..4a5b09df3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1313,47 +1313,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)) @@ -1934,7 +1893,7 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi + ((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 * (holdEffectAtk == HOLD_EFFECT_LEEK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD) + (abilityAtk == ABILITY_SUPER_LUCK); if (critChance >= ARRAY_COUNT(sCriticalHitChance)) @@ -3071,7 +3030,7 @@ void SetMoveEffect(bool32 primary, u32 certain) if (NoAliveMonsForEitherParty() || ChangeStatBuffs(SET_STAT_BUFF_VALUE(1), gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1, - affectsUser, 0)) + affectsUser | STAT_BUFF_UPDATE_MOVE_EFFECT, 0)) { gBattlescriptCurrInstr++; } @@ -3096,7 +3055,7 @@ void SetMoveEffect(bool32 primary, u32 certain) if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE, gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1, - flags, gBattlescriptCurrInstr + 1)) + flags | STAT_BUFF_UPDATE_MOVE_EFFECT, gBattlescriptCurrInstr + 1)) { if (!mirrorArmorReflected) gBattlescriptCurrInstr++; @@ -3119,7 +3078,7 @@ void SetMoveEffect(bool32 primary, u32 certain) if (NoAliveMonsForEitherParty() || ChangeStatBuffs(SET_STAT_BUFF_VALUE(2), gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1, - affectsUser, 0)) + affectsUser | STAT_BUFF_UPDATE_MOVE_EFFECT, 0)) { gBattlescriptCurrInstr++; } @@ -3143,7 +3102,7 @@ void SetMoveEffect(bool32 primary, u32 certain) flags |= STAT_BUFF_ALLOW_PTR; if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE, gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1, - flags, gBattlescriptCurrInstr + 1)) + flags | STAT_BUFF_UPDATE_MOVE_EFFECT, gBattlescriptCurrInstr + 1)) { if (!mirrorArmorReflected) gBattlescriptCurrInstr++; @@ -3205,7 +3164,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++; @@ -6200,8 +6163,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) @@ -6275,7 +6247,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; @@ -7466,7 +7438,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 } @@ -7934,6 +7906,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); @@ -8114,6 +8087,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; } @@ -9017,6 +8993,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!' { @@ -9815,6 +9800,72 @@ static void Cmd_setdrainedhp(void) gBattlescriptCurrInstr++; } +static u16 ReverseStatChangeMoveEffect(u16 moveEffect) +{ + switch (moveEffect) + { + // +1 + case MOVE_EFFECT_ATK_PLUS_1: + return MOVE_EFFECT_ATK_MINUS_1; + case MOVE_EFFECT_DEF_PLUS_1: + return MOVE_EFFECT_DEF_MINUS_1; + case MOVE_EFFECT_SPD_PLUS_1: + return MOVE_EFFECT_SPD_MINUS_1; + case MOVE_EFFECT_SP_ATK_PLUS_1: + return MOVE_EFFECT_SP_ATK_MINUS_1; + case MOVE_EFFECT_SP_DEF_PLUS_1: + return MOVE_EFFECT_SP_DEF_MINUS_1; + case MOVE_EFFECT_ACC_PLUS_1: + return MOVE_EFFECT_ACC_MINUS_1; + case MOVE_EFFECT_EVS_PLUS_1: + return MOVE_EFFECT_EVS_MINUS_1; + // -1 + case MOVE_EFFECT_ATK_MINUS_1: + return MOVE_EFFECT_ATK_PLUS_1; + case MOVE_EFFECT_DEF_MINUS_1: + return MOVE_EFFECT_DEF_PLUS_1; + case MOVE_EFFECT_SPD_MINUS_1: + return MOVE_EFFECT_SPD_PLUS_1; + case MOVE_EFFECT_SP_ATK_MINUS_1: + return MOVE_EFFECT_SP_ATK_PLUS_1; + case MOVE_EFFECT_SP_DEF_MINUS_1: + return MOVE_EFFECT_SP_DEF_PLUS_1; + case MOVE_EFFECT_ACC_MINUS_1: + return MOVE_EFFECT_ACC_PLUS_1; + case MOVE_EFFECT_EVS_MINUS_1: + // +2 + case MOVE_EFFECT_ATK_PLUS_2: + return MOVE_EFFECT_ATK_MINUS_2; + case MOVE_EFFECT_DEF_PLUS_2: + return MOVE_EFFECT_DEF_MINUS_2; + case MOVE_EFFECT_SPD_PLUS_2: + return MOVE_EFFECT_SPD_MINUS_2; + case MOVE_EFFECT_SP_ATK_PLUS_2: + return MOVE_EFFECT_SP_ATK_MINUS_2; + case MOVE_EFFECT_SP_DEF_PLUS_2: + return MOVE_EFFECT_SP_DEF_MINUS_2; + case MOVE_EFFECT_ACC_PLUS_2: + return MOVE_EFFECT_ACC_MINUS_2; + case MOVE_EFFECT_EVS_PLUS_2: + return MOVE_EFFECT_EVS_MINUS_2; + // -2 + case MOVE_EFFECT_ATK_MINUS_2: + return MOVE_EFFECT_ATK_PLUS_2; + case MOVE_EFFECT_DEF_MINUS_2: + return MOVE_EFFECT_DEF_PLUS_2; + case MOVE_EFFECT_SPD_MINUS_2: + return MOVE_EFFECT_SPD_PLUS_2; + case MOVE_EFFECT_SP_ATK_MINUS_2: + return MOVE_EFFECT_SP_ATK_PLUS_2; + case MOVE_EFFECT_SP_DEF_MINUS_2: + return MOVE_EFFECT_SP_DEF_PLUS_2; + case MOVE_EFFECT_ACC_MINUS_2: + return MOVE_EFFECT_ACC_PLUS_2; + case MOVE_EFFECT_EVS_MINUS_2: + return MOVE_EFFECT_EVS_PLUS_2; + } +} + static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr) { bool32 certain = FALSE; @@ -9843,6 +9894,11 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { statValue ^= STAT_BUFF_NEGATIVE; gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE; + if (flags & STAT_BUFF_UPDATE_MOVE_EFFECT) + { + flags &= ~(STAT_BUFF_UPDATE_MOVE_EFFECT); + gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect); + } } else if (GetBattlerAbility(gActiveBattler) == ABILITY_SIMPLE) { @@ -11361,11 +11417,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); @@ -12276,12 +12332,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 @@ -12314,6 +12371,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; } @@ -12594,25 +12654,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) @@ -13032,14 +13100,32 @@ static void Cmd_snatchsetbattlers(void) static void Cmd_removelightscreenreflect(void) // brick break { - u8 opposingSide = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; - - if (gSideTimers[opposingSide].reflectTimer || gSideTimers[opposingSide].lightscreenTimer) + u8 side; + bool32 failed; + + #if B_BRICK_BREAK >= GEN_4 + side = GetBattlerSide(gBattlerAttacker); + #else + side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; + #endif + + #if B_BRICK_BREAK >= GEN_5 + failed = (gMoveResultFlags & MOVE_RESULT_NO_EFFECT); + #else + failed = FALSE; + #endif + + if (!failed + && (gSideTimers[side].reflectTimer + || gSideTimers[side].lightscreenTimer + || gSideTimers[side].auroraVeilTimer)) { - gSideStatuses[opposingSide] &= ~(SIDE_STATUS_REFLECT); - gSideStatuses[opposingSide] &= ~(SIDE_STATUS_LIGHTSCREEN); - gSideTimers[opposingSide].reflectTimer = 0; - gSideTimers[opposingSide].lightscreenTimer = 0; + gSideStatuses[side] &= ~(SIDE_STATUS_REFLECT); + gSideStatuses[side] &= ~(SIDE_STATUS_LIGHTSCREEN); + gSideStatuses[side] &= ~(SIDE_STATUS_AURORA_VEIL); + gSideTimers[side].reflectTimer = 0; + gSideTimers[side].lightscreenTimer = 0; + gSideTimers[side].auroraVeilTimer = 0; gBattleScripting.animTurn = 1; gBattleScripting.animTargetsHit = 1; } @@ -13089,7 +13175,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 4b3fc11aa..1e29695e2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -317,8 +317,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++) @@ -387,9 +387,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; } @@ -627,7 +627,7 @@ bool8 TryRunFromBattle(u8 battler) effect++; } #endif - else if (gBattleMons[battler].ability == ABILITY_RUN_AWAY) + else if (GetBattlerAbility(battler) == ABILITY_RUN_AWAY) { if (InBattlePyramid()) { @@ -1762,7 +1762,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; @@ -1834,7 +1834,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]; @@ -2727,7 +2727,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); @@ -3311,7 +3311,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; @@ -3752,7 +3752,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; } @@ -3788,11 +3788,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; } @@ -3878,7 +3878,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]) @@ -5373,7 +5373,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)) @@ -5463,7 +5463,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) @@ -5524,7 +5524,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); @@ -5591,6 +5591,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) @@ -5601,11 +5618,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)) @@ -5615,8 +5672,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) @@ -5668,7 +5725,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 @@ -6860,8 +6917,10 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) switch (atkHoldEffect) { case HOLD_EFFECT_FLINCH: - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_SERENE_GRACE) - atkHoldEffectParam *= 2; + #if B_SERENE_GRACE_BOOST >= GEN_5 + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_SERENE_GRACE) + atkHoldEffectParam *= 2; + #endif if (gBattleMoveDamage != 0 // Need to have done damage && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED @@ -7217,7 +7276,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); @@ -7225,7 +7284,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); @@ -7403,7 +7462,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 && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID)) return HOLD_EFFECT_NONE; } @@ -7448,6 +7507,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) @@ -8030,7 +8131,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 @@ -8191,8 +8292,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; } @@ -8607,7 +8711,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)); @@ -8779,9 +8885,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) { @@ -9005,9 +9108,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");