2017-09-17 14:10:32 +02:00
# include "global.h"
# include "battle.h"
2019-03-31 19:15:39 +02:00
# include "battle_anim.h"
2020-10-26 10:52:00 +01:00
# include "battle_arena.h"
# include "battle_pyramid.h"
# include "battle_util.h"
2018-11-15 21:53:32 +01:00
# include "battle_controllers.h"
2018-07-14 22:56:03 +02:00
# include "battle_interface.h"
2019-01-27 20:54:34 +01:00
# include "battle_setup.h"
2019-08-08 13:06:55 +02:00
# include "party_menu.h"
2017-09-17 14:10:32 +02:00
# include "pokemon.h"
2020-10-26 10:52:00 +01:00
# include "international_string_util.h"
2017-09-17 14:10:32 +02:00
# include "item.h"
# include "util.h"
2017-11-25 18:42:31 +01:00
# include "battle_scripts.h"
2017-12-05 19:27:33 +01:00
# include "random.h"
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
# include "text.h"
2020-10-26 10:52:00 +01:00
# include "safari_zone.h"
# include "sound.h"
# include "sprite.h"
2017-09-17 14:10:32 +02:00
# include "string_util.h"
2020-10-26 10:52:00 +01:00
# include "task.h"
# include "trig.h"
# include "window.h"
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
# include "battle_message.h"
2020-12-20 22:47:20 +01:00
# include "battle_ai_main.h"
2020-12-16 05:57:33 +01:00
# include "battle_ai_util.h"
2017-09-17 17:14:32 +02:00
# include "event_data.h"
2017-10-06 17:06:45 +02:00
# include "link.h"
2020-04-28 15:36:13 +02:00
# include "malloc.h"
2017-11-27 21:24:34 +01:00
# include "berry.h"
2018-07-14 16:41:14 +02:00
# include "pokedex.h"
2018-09-30 12:27:51 +02:00
# include "mail.h"
2018-12-08 19:43:21 +01:00
# include "field_weather.h"
2019-09-16 05:47:07 +02:00
# include "constants/abilities.h"
# include "constants/battle_anim.h"
2020-02-08 14:20:02 +01:00
# include "constants/battle_config.h"
2019-09-16 05:47:07 +02:00
# include "constants/battle_move_effects.h"
# include "constants/battle_script_commands.h"
# include "constants/battle_string_ids.h"
# include "constants/hold_effects.h"
# include "constants/items.h"
# include "constants/moves.h"
2020-09-08 22:44:04 +02:00
# include "constants/songs.h"
2019-09-16 05:47:07 +02:00
# include "constants/species.h"
2020-10-21 16:44:03 +02:00
# include "constants/trainers.h"
2019-09-16 05:47:07 +02:00
# include "constants/weather.h"
2017-10-06 17:06:45 +02:00
2021-06-07 21:00:23 +02:00
extern struct Evolution gEvolutionTable [ ] [ EVOS_PER_MON ] ;
2020-10-26 10:52:00 +01:00
/*
NOTE : The data and functions in this file up until ( but not including ) sSoundMovesTable
are actually part of battle_main . c . They needed to be moved to this file in order to
match the ROM ; this is also why sSoundMovesTable ' s declaration is in the middle of
functions instead of at the top of the file with the other declarations .
*/
2020-09-08 22:44:04 +02:00
2021-01-05 23:44:12 +01:00
static bool32 TryRemoveScreens ( u8 battler ) ;
2021-01-06 03:37:23 +01:00
static bool32 IsUnnerveAbilityOnOpposingSide ( u8 battlerId ) ;
2021-01-05 23:44:12 +01:00
2020-09-08 22:44:04 +02:00
extern const u8 * const gBattleScriptsForMoveEffects [ ] ;
extern const u8 * const gBattlescriptsForBallThrow [ ] ;
extern const u8 * const gBattlescriptsForRunningByItem [ ] ;
extern const u8 * const gBattlescriptsForUsingItem [ ] ;
extern const u8 * const gBattlescriptsForSafariActions [ ] ;
2021-04-02 08:27:12 +02:00
static const u8 sPkblToEscapeFactor [ ] [ 3 ] = {
{
[ B_MSG_MON_CURIOUS ] = 0 ,
[ B_MSG_MON_ENTHRALLED ] = 0 ,
[ B_MSG_MON_IGNORED ] = 0
} , {
[ B_MSG_MON_CURIOUS ] = 3 ,
[ B_MSG_MON_ENTHRALLED ] = 5 ,
[ B_MSG_MON_IGNORED ] = 0
} , {
[ B_MSG_MON_CURIOUS ] = 2 ,
[ B_MSG_MON_ENTHRALLED ] = 3 ,
[ B_MSG_MON_IGNORED ] = 0
} , {
[ B_MSG_MON_CURIOUS ] = 1 ,
[ B_MSG_MON_ENTHRALLED ] = 2 ,
[ B_MSG_MON_IGNORED ] = 0
} , {
[ B_MSG_MON_CURIOUS ] = 1 ,
[ B_MSG_MON_ENTHRALLED ] = 1 ,
[ B_MSG_MON_IGNORED ] = 0
}
} ;
2020-09-08 22:44:04 +02:00
static const u8 sGoNearCounterToCatchFactor [ ] = { 4 , 3 , 2 , 1 } ;
static const u8 sGoNearCounterToEscapeFactor [ ] = { 4 , 4 , 4 , 4 } ;
2021-06-10 12:55:05 +02:00
static const u16 sSkillSwapBannedAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
ABILITY_WONDER_GUARD ,
ABILITY_MULTITYPE ,
ABILITY_ILLUSION ,
ABILITY_STANCE_CHANGE ,
ABILITY_SCHOOLING ,
ABILITY_COMATOSE ,
ABILITY_SHIELDS_DOWN ,
ABILITY_DISGUISE ,
ABILITY_RKS_SYSTEM ,
ABILITY_BATTLE_BOND ,
ABILITY_POWER_CONSTRUCT ,
ABILITY_NEUTRALIZING_GAS ,
ABILITY_ICE_FACE ,
ABILITY_HUNGER_SWITCH ,
ABILITY_GULP_MISSILE ,
} ;
2021-06-10 12:55:05 +02:00
static const u16 sRolePlayBannedAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
2021-06-10 12:55:05 +02:00
ABILITY_TRACE ,
2020-12-13 23:02:21 +01:00
ABILITY_WONDER_GUARD ,
ABILITY_FORECAST ,
ABILITY_FLOWER_GIFT ,
ABILITY_MULTITYPE ,
ABILITY_ILLUSION ,
ABILITY_ZEN_MODE ,
ABILITY_IMPOSTER ,
ABILITY_STANCE_CHANGE ,
ABILITY_POWER_OF_ALCHEMY ,
ABILITY_RECEIVER ,
ABILITY_SCHOOLING ,
ABILITY_COMATOSE ,
ABILITY_SHIELDS_DOWN ,
ABILITY_DISGUISE ,
ABILITY_RKS_SYSTEM ,
ABILITY_BATTLE_BOND ,
ABILITY_POWER_CONSTRUCT ,
ABILITY_ICE_FACE ,
ABILITY_HUNGER_SWITCH ,
ABILITY_GULP_MISSILE ,
} ;
2021-06-10 12:55:05 +02:00
static const u16 sRolePlayBannedAttackerAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
ABILITY_MULTITYPE ,
ABILITY_ZEN_MODE ,
ABILITY_STANCE_CHANGE ,
ABILITY_SCHOOLING ,
ABILITY_COMATOSE ,
ABILITY_SHIELDS_DOWN ,
ABILITY_DISGUISE ,
ABILITY_RKS_SYSTEM ,
ABILITY_BATTLE_BOND ,
ABILITY_POWER_CONSTRUCT ,
ABILITY_ICE_FACE ,
ABILITY_GULP_MISSILE ,
} ;
2021-06-10 12:55:05 +02:00
static const u16 sWorrySeedBannedAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
ABILITY_MULTITYPE ,
ABILITY_STANCE_CHANGE ,
ABILITY_SCHOOLING ,
ABILITY_COMATOSE ,
ABILITY_SHIELDS_DOWN ,
ABILITY_DISGUISE ,
ABILITY_RKS_SYSTEM ,
ABILITY_BATTLE_BOND ,
ABILITY_POWER_CONSTRUCT ,
ABILITY_TRUANT ,
ABILITY_ICE_FACE ,
ABILITY_GULP_MISSILE ,
} ;
2021-06-10 12:55:05 +02:00
static const u16 sGastroAcidBannedAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
2021-02-12 16:59:55 +01:00
ABILITY_AS_ONE_ICE_RIDER ,
ABILITY_AS_ONE_SHADOW_RIDER ,
ABILITY_BATTLE_BOND ,
2020-12-13 23:02:21 +01:00
ABILITY_COMATOSE ,
ABILITY_DISGUISE ,
ABILITY_GULP_MISSILE ,
2021-02-12 16:59:55 +01:00
ABILITY_ICE_FACE ,
ABILITY_MULTITYPE ,
ABILITY_POWER_CONSTRUCT ,
ABILITY_RKS_SYSTEM ,
ABILITY_SCHOOLING ,
ABILITY_SHIELDS_DOWN ,
ABILITY_STANCE_CHANGE ,
ABILITY_ZEN_MODE ,
2020-12-13 23:02:21 +01:00
} ;
2021-06-10 12:55:05 +02:00
static const u16 sEntrainmentBannedAttackerAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
ABILITY_TRACE ,
ABILITY_FORECAST ,
ABILITY_FLOWER_GIFT ,
ABILITY_ZEN_MODE ,
ABILITY_ILLUSION ,
ABILITY_IMPOSTER ,
ABILITY_POWER_OF_ALCHEMY ,
ABILITY_RECEIVER ,
ABILITY_DISGUISE ,
ABILITY_POWER_CONSTRUCT ,
ABILITY_NEUTRALIZING_GAS ,
ABILITY_ICE_FACE ,
ABILITY_HUNGER_SWITCH ,
ABILITY_GULP_MISSILE ,
} ;
2021-06-10 12:55:05 +02:00
static const u16 sEntrainmentTargetSimpleBeamBannedAbilities [ ] =
2020-12-13 23:02:21 +01:00
{
ABILITY_TRUANT ,
ABILITY_MULTITYPE ,
ABILITY_STANCE_CHANGE ,
ABILITY_SCHOOLING ,
ABILITY_COMATOSE ,
ABILITY_SHIELDS_DOWN ,
ABILITY_DISGUISE ,
ABILITY_RKS_SYSTEM ,
ABILITY_BATTLE_BOND ,
ABILITY_ICE_FACE ,
ABILITY_GULP_MISSILE ,
} ;
2021-07-25 16:22:05 +02:00
bool32 IsAffectedByFollowMe ( u32 battlerAtk , u32 defSide , u32 move )
2021-06-10 12:55:05 +02:00
{
u32 ability = GetBattlerAbility ( battlerAtk ) ;
if ( gSideTimers [ defSide ] . followmeTimer = = 0
| | gBattleMons [ gSideTimers [ defSide ] . followmeTarget ] . hp = = 0
2021-07-25 16:22:05 +02:00
| | gBattleMoves [ move ] . effect = = EFFECT_SNIPE_SHOT
2021-06-10 12:55:05 +02:00
| | ability = = ABILITY_PROPELLER_TAIL | | ability = = ABILITY_STALWART )
return FALSE ;
if ( gSideTimers [ defSide ] . followmePowder & & ! IsAffectedByPowder ( battlerAtk , ability , GetBattlerHoldEffect ( battlerAtk , TRUE ) ) )
return FALSE ;
return TRUE ;
}
2020-12-13 23:02:21 +01:00
// Functions
2020-09-08 22:44:04 +02:00
void HandleAction_UseMove ( void )
{
2020-10-11 06:57:16 +02:00
u32 i , side , moveType , var = 4 ;
2021-11-24 00:09:54 +01:00
u16 moveTarget = GetBattlerMoveTargetType ( gBattlerAttacker , gCurrentMove ) ;
2020-09-08 22:44:04 +02:00
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
2020-10-11 06:57:16 +02:00
if ( gBattleStruct - > field_91 & gBitTable [ gBattlerAttacker ] | | ! IsBattlerAlive ( gBattlerAttacker ) )
2020-09-08 22:44:04 +02:00
{
gCurrentActionFuncId = B_ACTION_FINISHED ;
return ;
}
2020-10-11 06:57:16 +02:00
gIsCriticalHit = FALSE ;
2020-09-08 22:44:04 +02:00
gBattleStruct - > atkCancellerTracker = 0 ;
gMoveResultFlags = 0 ;
gMultiHitCounter = 0 ;
gBattleCommunication [ 6 ] = 0 ;
2020-10-11 06:57:16 +02:00
gBattleScripting . savedMoveEffect = 0 ;
2020-09-08 22:44:04 +02:00
gCurrMovePos = gChosenMovePos = * ( gBattleStruct - > chosenMovePositions + gBattlerAttacker ) ;
// choose move
if ( gProtectStructs [ gBattlerAttacker ] . noValidMoves )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . noValidMoves = FALSE ;
2020-09-08 22:44:04 +02:00
gCurrentMove = gChosenMove = MOVE_STRUGGLE ;
gHitMarker | = HITMARKER_NO_PPDEDUCT ;
* ( gBattleStruct - > moveTarget + gBattlerAttacker ) = GetMoveTarget ( MOVE_STRUGGLE , 0 ) ;
}
else if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_MULTIPLETURNS | | gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_RECHARGE )
{
gCurrentMove = gChosenMove = gLockedMoves [ gBattlerAttacker ] ;
}
// encore forces you to use the same move
else if ( gDisableStructs [ gBattlerAttacker ] . encoredMove ! = MOVE_NONE
2021-04-04 13:44:32 +02:00
& & gDisableStructs [ gBattlerAttacker ] . encoredMove = = gBattleMons [ gBattlerAttacker ] . moves [ gDisableStructs [ gBattlerAttacker ] . encoredMovePos ] )
2020-09-08 22:44:04 +02:00
{
gCurrentMove = gChosenMove = gDisableStructs [ gBattlerAttacker ] . encoredMove ;
gCurrMovePos = gChosenMovePos = gDisableStructs [ gBattlerAttacker ] . encoredMovePos ;
* ( gBattleStruct - > moveTarget + gBattlerAttacker ) = GetMoveTarget ( gCurrentMove , 0 ) ;
}
// check if the encored move wasn't overwritten
else if ( gDisableStructs [ gBattlerAttacker ] . encoredMove ! = MOVE_NONE
2021-04-04 13:44:32 +02:00
& & gDisableStructs [ gBattlerAttacker ] . encoredMove ! = gBattleMons [ gBattlerAttacker ] . moves [ gDisableStructs [ gBattlerAttacker ] . encoredMovePos ] )
2020-09-08 22:44:04 +02:00
{
gCurrMovePos = gChosenMovePos = gDisableStructs [ gBattlerAttacker ] . encoredMovePos ;
gCurrentMove = gChosenMove = gBattleMons [ gBattlerAttacker ] . moves [ gCurrMovePos ] ;
gDisableStructs [ gBattlerAttacker ] . encoredMove = MOVE_NONE ;
gDisableStructs [ gBattlerAttacker ] . encoredMovePos = 0 ;
gDisableStructs [ gBattlerAttacker ] . encoreTimer = 0 ;
* ( gBattleStruct - > moveTarget + gBattlerAttacker ) = GetMoveTarget ( gCurrentMove , 0 ) ;
}
else if ( gBattleMons [ gBattlerAttacker ] . moves [ gCurrMovePos ] ! = gChosenMoveByBattler [ gBattlerAttacker ] )
{
gCurrentMove = gChosenMove = gBattleMons [ gBattlerAttacker ] . moves [ gCurrMovePos ] ;
* ( gBattleStruct - > moveTarget + gBattlerAttacker ) = GetMoveTarget ( gCurrentMove , 0 ) ;
}
else
{
gCurrentMove = gChosenMove = gBattleMons [ gBattlerAttacker ] . moves [ gCurrMovePos ] ;
}
if ( gBattleMons [ gBattlerAttacker ] . hp ! = 0 )
{
if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_PLAYER )
gBattleResults . lastUsedMovePlayer = gCurrentMove ;
else
gBattleResults . lastUsedMoveOpponent = gCurrentMove ;
}
2020-10-11 06:57:16 +02:00
// Set dynamic move type.
SetTypeBeforeUsingMove ( gChosenMove , gBattlerAttacker ) ;
GET_MOVE_TYPE ( gChosenMove , moveType ) ;
2020-09-08 22:44:04 +02:00
// choose target
side = GetBattlerSide ( gBattlerAttacker ) ^ BIT_SIDE ;
2021-07-25 16:22:05 +02:00
if ( IsAffectedByFollowMe ( gBattlerAttacker , side , gCurrentMove )
2021-11-23 04:56:11 +01:00
& & moveTarget = = MOVE_TARGET_SELECTED
2021-06-10 12:55:05 +02:00
& & GetBattlerSide ( gBattlerAttacker ) ! = GetBattlerSide ( gSideTimers [ side ] . followmeTarget ) )
2020-09-08 22:44:04 +02:00
{
gBattlerTarget = gSideTimers [ side ] . followmeTarget ;
}
else if ( ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
2021-04-04 13:44:32 +02:00
& & gSideTimers [ side ] . followmeTimer = = 0
2021-11-23 04:56:11 +01:00
& & ( gBattleMoves [ gCurrentMove ] . power ! = 0 | | moveTarget ! = MOVE_TARGET_USER )
2021-10-31 22:19:30 +01:00
& & ( ( GetBattlerAbility ( * ( gBattleStruct - > moveTarget + gBattlerAttacker ) ) ! = ABILITY_LIGHTNING_ROD & & moveType = = TYPE_ELECTRIC )
| | ( GetBattlerAbility ( * ( gBattleStruct - > moveTarget + gBattlerAttacker ) ) ! = ABILITY_STORM_DRAIN & & moveType = = TYPE_WATER ) ) )
2020-09-08 22:44:04 +02:00
{
side = GetBattlerSide ( gBattlerAttacker ) ;
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
{
if ( side ! = GetBattlerSide ( gActiveBattler )
& & * ( gBattleStruct - > moveTarget + gBattlerAttacker ) ! = gActiveBattler
2020-10-11 06:57:16 +02:00
& & ( ( GetBattlerAbility ( gActiveBattler ) = = ABILITY_LIGHTNING_ROD & & moveType = = TYPE_ELECTRIC )
2021-04-04 13:44:32 +02:00
| | ( GetBattlerAbility ( gActiveBattler ) = = ABILITY_STORM_DRAIN & & moveType = = TYPE_WATER ) )
2020-12-03 03:23:34 +01:00
& & GetBattlerTurnOrderNum ( gActiveBattler ) < var
2021-01-28 21:27:00 +01:00
& & gBattleMoves [ gCurrentMove ] . effect ! = EFFECT_SNIPE_SHOT
2020-12-05 18:14:26 +01:00
& & ( GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_PROPELLER_TAIL
2021-04-04 13:44:32 +02:00
| | GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_STALWART ) )
2020-09-08 22:44:04 +02:00
{
var = GetBattlerTurnOrderNum ( gActiveBattler ) ;
}
}
if ( var = = 4 )
{
2021-11-23 04:56:11 +01:00
if ( moveTarget & MOVE_TARGET_RANDOM )
2020-09-08 22:44:04 +02:00
{
if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_PLAYER )
{
if ( Random ( ) & 1 )
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
else
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
}
else
{
if ( Random ( ) & 1 )
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
else
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
}
}
2021-11-23 04:56:11 +01:00
else if ( moveTarget & MOVE_TARGET_FOES_AND_ALLY )
2020-10-11 06:57:16 +02:00
{
for ( gBattlerTarget = 0 ; gBattlerTarget < gBattlersCount ; gBattlerTarget + + )
{
if ( gBattlerTarget = = gBattlerAttacker )
continue ;
if ( IsBattlerAlive ( gBattlerTarget ) )
break ;
}
}
2020-09-08 22:44:04 +02:00
else
{
gBattlerTarget = * ( gBattleStruct - > moveTarget + gBattlerAttacker ) ;
}
2020-10-11 06:57:16 +02:00
if ( ! IsBattlerAlive ( gBattlerTarget ) )
2020-09-08 22:44:04 +02:00
{
if ( GetBattlerSide ( gBattlerAttacker ) ! = GetBattlerSide ( gBattlerTarget ) )
{
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerTarget ) ^ BIT_FLANK ) ;
}
else
{
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerAttacker ) ^ BIT_SIDE ) ;
2020-10-11 06:57:16 +02:00
if ( ! IsBattlerAlive ( gBattlerTarget ) )
2020-09-08 22:44:04 +02:00
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerTarget ) ^ BIT_FLANK ) ;
}
}
}
else
{
gActiveBattler = gBattlerByTurnOrder [ var ] ;
RecordAbilityBattle ( gActiveBattler , gBattleMons [ gActiveBattler ] . ability ) ;
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( gActiveBattler ) = = ABILITY_LIGHTNING_ROD )
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ gActiveBattler ] . lightningRodRedirected = TRUE ;
2021-10-31 22:19:30 +01:00
else if ( GetBattlerAbility ( gActiveBattler ) = = ABILITY_STORM_DRAIN )
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ gActiveBattler ] . stormDrainRedirected = TRUE ;
2020-09-08 22:44:04 +02:00
gBattlerTarget = gActiveBattler ;
}
}
else if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE
2021-11-23 04:56:11 +01:00
& & moveTarget & MOVE_TARGET_RANDOM )
2020-09-08 22:44:04 +02:00
{
if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_PLAYER )
{
if ( Random ( ) & 1 )
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
else
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
}
else
{
if ( Random ( ) & 1 )
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
else
gBattlerTarget = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
}
if ( gAbsentBattlerFlags & gBitTable [ gBattlerTarget ]
& & GetBattlerSide ( gBattlerAttacker ) ! = GetBattlerSide ( gBattlerTarget ) )
{
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerTarget ) ^ BIT_FLANK ) ;
}
}
2021-11-23 04:56:11 +01:00
else if ( moveTarget = = MOVE_TARGET_ALLY )
2020-10-11 06:57:16 +02:00
{
if ( IsBattlerAlive ( BATTLE_PARTNER ( gBattlerAttacker ) ) )
gBattlerTarget = BATTLE_PARTNER ( gBattlerAttacker ) ;
else
gBattlerTarget = gBattlerAttacker ;
}
else if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE
2021-11-23 04:56:11 +01:00
& & moveTarget = = MOVE_TARGET_FOES_AND_ALLY )
2020-10-11 06:57:16 +02:00
{
for ( gBattlerTarget = 0 ; gBattlerTarget < gBattlersCount ; gBattlerTarget + + )
{
if ( gBattlerTarget = = gBattlerAttacker )
continue ;
if ( IsBattlerAlive ( gBattlerTarget ) )
break ;
}
}
2020-09-08 22:44:04 +02:00
else
{
gBattlerTarget = * ( gBattleStruct - > moveTarget + gBattlerAttacker ) ;
2020-10-11 06:57:16 +02:00
if ( ! IsBattlerAlive ( gBattlerTarget ) )
2020-09-08 22:44:04 +02:00
{
if ( GetBattlerSide ( gBattlerAttacker ) ! = GetBattlerSide ( gBattlerTarget ) )
{
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerTarget ) ^ BIT_FLANK ) ;
}
else
{
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerAttacker ) ^ BIT_SIDE ) ;
2020-10-11 06:57:16 +02:00
if ( ! IsBattlerAlive ( gBattlerTarget ) )
2020-09-08 22:44:04 +02:00
gBattlerTarget = GetBattlerAtPosition ( GetBattlerPosition ( gBattlerTarget ) ^ BIT_FLANK ) ;
}
}
}
2021-04-02 08:27:12 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE & & gProtectStructs [ gBattlerAttacker ] . palaceUnableToUseMove )
2020-09-08 22:44:04 +02:00
{
2021-04-02 08:27:12 +02:00
// Battle Palace, select battle script for failure to use move
2020-09-08 22:44:04 +02:00
if ( gBattleMons [ gBattlerAttacker ] . hp = = 0 )
{
gCurrentActionFuncId = B_ACTION_FINISHED ;
return ;
}
else if ( gPalaceSelectionBattleScripts [ gBattlerAttacker ] ! = NULL )
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_INCAPABLE_OF_POWER ;
2020-09-08 22:44:04 +02:00
gBattlescriptCurrInstr = gPalaceSelectionBattleScripts [ gBattlerAttacker ] ;
gPalaceSelectionBattleScripts [ gBattlerAttacker ] = NULL ;
}
else
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_INCAPABLE_OF_POWER ;
2020-09-08 22:44:04 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
}
}
else
{
gBattlescriptCurrInstr = gBattleScriptsForMoveEffects [ gBattleMoves [ gCurrentMove ] . effect ] ;
}
if ( gBattleTypeFlags & BATTLE_TYPE_ARENA )
BattleArena_AddMindPoints ( gBattlerAttacker ) ;
2020-10-11 06:57:16 +02:00
// Record HP of each battler
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
gBattleStruct - > hpBefore [ i ] = gBattleMons [ i ] . hp ;
2020-09-08 22:44:04 +02:00
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
void HandleAction_Switch ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gActionSelectionCursor [ gBattlerAttacker ] = 0 ;
gMoveSelectionCursor [ gBattlerAttacker ] = 0 ;
PREPARE_MON_NICK_BUFFER ( gBattleTextBuff1 , gBattlerAttacker , * ( gBattleStruct - > field_58 + gBattlerAttacker ) )
gBattleScripting . battler = gBattlerAttacker ;
gBattlescriptCurrInstr = BattleScript_ActionSwitch ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
if ( gBattleResults . playerSwitchesCounter < 255 )
gBattleResults . playerSwitchesCounter + + ;
2020-10-11 06:57:16 +02:00
2021-07-16 07:56:53 +02:00
UndoFormChange ( gBattlerPartyIndexes [ gBattlerAttacker ] , GetBattlerSide ( gBattlerAttacker ) , TRUE ) ;
2020-09-08 22:44:04 +02:00
}
void HandleAction_UseItem ( void )
{
gBattlerAttacker = gBattlerTarget = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
ClearFuryCutterDestinyBondGrudge ( gBattlerAttacker ) ;
2020-10-13 16:40:01 +02:00
2020-10-11 06:57:16 +02:00
gLastUsedItem = gBattleResources - > bufferB [ gBattlerAttacker ] [ 1 ] | ( gBattleResources - > bufferB [ gBattlerAttacker ] [ 2 ] < < 8 ) ;
2020-09-08 22:44:04 +02:00
if ( gLastUsedItem < = LAST_BALL ) // is ball
{
gBattlescriptCurrInstr = gBattlescriptsForBallThrow [ gLastUsedItem ] ;
}
else if ( gLastUsedItem = = ITEM_POKE_DOLL | | gLastUsedItem = = ITEM_FLUFFY_TAIL )
{
gBattlescriptCurrInstr = gBattlescriptsForRunningByItem [ 0 ] ;
}
else if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_PLAYER )
{
gBattlescriptCurrInstr = gBattlescriptsForUsingItem [ 0 ] ;
}
else
{
gBattleScripting . battler = gBattlerAttacker ;
switch ( * ( gBattleStruct - > AI_itemType + ( gBattlerAttacker > > 1 ) ) )
{
case AI_ITEM_FULL_RESTORE :
case AI_ITEM_HEAL_HP :
break ;
case AI_ITEM_CURE_CONDITION :
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = AI_HEAL_CONFUSION ;
if ( * ( gBattleStruct - > AI_itemFlags + gBattlerAttacker / 2 ) & ( 1 < < AI_HEAL_CONFUSION ) )
2020-09-08 22:44:04 +02:00
{
2020-10-26 10:52:00 +01:00
if ( * ( gBattleStruct - > AI_itemFlags + gBattlerAttacker / 2 ) & 0x3E )
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = AI_HEAL_SLEEP ;
2020-09-08 22:44:04 +02:00
}
else
{
2021-04-02 08:27:12 +02:00
// Check for other statuses, stopping at first (shouldn't be more than one)
2020-10-26 10:52:00 +01:00
while ( ! ( * ( gBattleStruct - > AI_itemFlags + gBattlerAttacker / 2 ) & 1 ) )
2020-09-08 22:44:04 +02:00
{
2020-10-26 10:52:00 +01:00
* ( gBattleStruct - > AI_itemFlags + gBattlerAttacker / 2 ) > > = 1 ;
2020-09-08 22:44:04 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] + + ;
2021-04-02 08:27:12 +02:00
// MULTISTRING_CHOOSER will be either AI_HEAL_PARALYSIS, AI_HEAL_FREEZE,
// AI_HEAL_BURN, AI_HEAL_POISON, or AI_HEAL_SLEEP
2020-10-26 10:52:00 +01:00
}
2020-09-08 22:44:04 +02:00
}
break ;
case AI_ITEM_X_STAT :
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_STAT_ROSE_ITEM ;
if ( * ( gBattleStruct - > AI_itemFlags + ( gBattlerAttacker > > 1 ) ) & ( 1 < < AI_DIRE_HIT ) )
2020-09-08 22:44:04 +02:00
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_USED_DIRE_HIT ;
2020-09-08 22:44:04 +02:00
}
else
{
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_ATK )
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , CHAR_X )
while ( ! ( ( * ( gBattleStruct - > AI_itemFlags + ( gBattlerAttacker > > 1 ) ) ) & 1 ) )
{
2020-10-26 10:52:00 +01:00
* ( gBattleStruct - > AI_itemFlags + gBattlerAttacker / 2 ) > > = 1 ;
2020-09-08 22:44:04 +02:00
gBattleTextBuff1 [ 2 ] + + ;
}
gBattleScripting . animArg1 = gBattleTextBuff1 [ 2 ] + 14 ;
gBattleScripting . animArg2 = 0 ;
}
break ;
2021-04-03 21:18:17 +02:00
case AI_ITEM_GUARD_SPEC :
// It seems probable that at some point there was a special message for
// an AI trainer using Guard Spec in a double battle.
// There isn't now however, and the assignment to 2 below goes out of
// bounds for gMistUsedStringIds and instead prints "{mon} is getting pumped"
// from the next table, gFocusEnergyUsedStringIds.
// In any case this isn't an issue in the retail version, as no trainers
// are ever given any Guard Spec to use.
# ifndef UBFIX
2020-09-08 22:44:04 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
gBattleCommunication [ MULTISTRING_CHOOSER ] = 2 ;
else
2021-04-03 21:18:17 +02:00
# endif
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SET_MIST ;
2020-09-08 22:44:04 +02:00
break ;
}
2020-10-26 10:52:00 +01:00
gBattlescriptCurrInstr = gBattlescriptsForUsingItem [ * ( gBattleStruct - > AI_itemType + gBattlerAttacker / 2 ) ] ;
2020-09-08 22:44:04 +02:00
}
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
bool8 TryRunFromBattle ( u8 battler )
{
bool8 effect = FALSE ;
u8 holdEffect ;
u8 pyramidMultiplier ;
u8 speedVar ;
if ( gBattleMons [ battler ] . item = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ battler ] . holdEffect ;
else
holdEffect = ItemId_GetHoldEffect ( gBattleMons [ battler ] . item ) ;
gPotentialItemEffectBattler = battler ;
if ( holdEffect = = HOLD_EFFECT_CAN_ALWAYS_RUN )
{
gLastUsedItem = gBattleMons [ battler ] . item ;
gProtectStructs [ battler ] . fleeFlag = 1 ;
effect + + ;
}
2021-10-23 16:41:31 +02:00
# if B_GHOSTS_ESCAPE >= GEN_6
else if ( IS_BATTLER_OF_TYPE ( battler , TYPE_GHOST ) )
{
effect + + ;
}
# endif
2021-10-30 18:06:02 +02:00
else if ( GetBattlerAbility ( battler ) = = ABILITY_RUN_AWAY )
2020-09-08 22:44:04 +02:00
{
if ( InBattlePyramid ( ) )
{
gBattleStruct - > runTries + + ;
pyramidMultiplier = GetPyramidRunMultiplier ( ) ;
speedVar = ( gBattleMons [ battler ] . speed * pyramidMultiplier ) / ( gBattleMons [ BATTLE_OPPOSITE ( battler ) ] . speed ) + ( gBattleStruct - > runTries * 30 ) ;
if ( speedVar > ( Random ( ) & 0xFF ) )
{
gLastUsedAbility = ABILITY_RUN_AWAY ;
gProtectStructs [ battler ] . fleeFlag = 2 ;
effect + + ;
}
}
else
{
gLastUsedAbility = ABILITY_RUN_AWAY ;
gProtectStructs [ battler ] . fleeFlag = 2 ;
effect + + ;
}
}
else if ( gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER | BATTLE_TYPE_TRAINER_HILL ) & & gBattleTypeFlags & BATTLE_TYPE_TRAINER )
{
effect + + ;
}
else
{
2020-10-11 06:57:16 +02:00
u8 runningFromBattler = BATTLE_OPPOSITE ( battler ) ;
if ( ! IsBattlerAlive ( runningFromBattler ) )
runningFromBattler | = BIT_FLANK ;
if ( InBattlePyramid ( ) )
2020-09-08 22:44:04 +02:00
{
2020-10-11 06:57:16 +02:00
pyramidMultiplier = GetPyramidRunMultiplier ( ) ;
speedVar = ( gBattleMons [ battler ] . speed * pyramidMultiplier ) / ( gBattleMons [ runningFromBattler ] . speed ) + ( gBattleStruct - > runTries * 30 ) ;
if ( speedVar > ( Random ( ) & 0xFF ) )
2020-09-08 22:44:04 +02:00
effect + + ;
2020-10-11 06:57:16 +02:00
}
else if ( gBattleMons [ battler ] . speed < gBattleMons [ runningFromBattler ] . speed )
{
speedVar = ( gBattleMons [ battler ] . speed * 128 ) / ( gBattleMons [ runningFromBattler ] . speed ) + ( gBattleStruct - > runTries * 30 ) ;
if ( speedVar > ( Random ( ) & 0xFF ) )
effect + + ;
}
else // same speed or faster
{
effect + + ;
2020-09-08 22:44:04 +02:00
}
gBattleStruct - > runTries + + ;
}
if ( effect )
{
gCurrentTurnActionNumber = gBattlersCount ;
gBattleOutcome = B_OUTCOME_RAN ;
}
return effect ;
}
void HandleAction_Run ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
2021-01-13 21:17:32 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) )
2020-09-08 22:44:04 +02:00
{
gCurrentTurnActionNumber = gBattlersCount ;
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
{
if ( GetBattlerSide ( gActiveBattler ) = = B_SIDE_PLAYER )
{
if ( gChosenActionByBattler [ gActiveBattler ] = = B_ACTION_RUN )
gBattleOutcome | = B_OUTCOME_LOST ;
}
else
{
if ( gChosenActionByBattler [ gActiveBattler ] = = B_ACTION_RUN )
gBattleOutcome | = B_OUTCOME_WON ;
}
}
gBattleOutcome | = B_OUTCOME_LINK_BATTLE_RAN ;
gSaveBlock2Ptr - > frontier . disableRecordBattle = TRUE ;
}
else
{
if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_PLAYER )
{
if ( ! TryRunFromBattle ( gBattlerAttacker ) ) // failed to run away
{
ClearFuryCutterDestinyBondGrudge ( gBattlerAttacker ) ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CANT_ESCAPE_2 ;
2020-09-08 22:44:04 +02:00
gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
}
else
{
2020-10-11 06:57:16 +02:00
if ( ! CanBattlerEscape ( gBattlerAttacker ) )
2020-09-08 22:44:04 +02:00
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_ATTACKER_CANT_ESCAPE ;
2020-09-08 22:44:04 +02:00
gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
else
{
gCurrentTurnActionNumber = gBattlersCount ;
gBattleOutcome = B_OUTCOME_MON_FLED ;
}
}
}
}
void HandleAction_WatchesCarefully ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gBattlescriptCurrInstr = gBattlescriptsForSafariActions [ 0 ] ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
void HandleAction_SafariZoneBallThrow ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gNumSafariBalls - - ;
gLastUsedItem = ITEM_SAFARI_BALL ;
gBattlescriptCurrInstr = gBattlescriptsForBallThrow [ ITEM_SAFARI_BALL ] ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
2021-06-25 21:37:59 +02:00
void HandleAction_ThrowBall ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
2021-09-23 18:03:01 +02:00
gLastUsedItem = gLastThrownBall ;
2021-06-25 21:37:59 +02:00
RemoveBagItem ( gLastUsedItem , 1 ) ;
gBattlescriptCurrInstr = BattleScript_BallThrow ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
2020-09-08 22:44:04 +02:00
void HandleAction_ThrowPokeblock ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
2020-10-11 06:57:16 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = gBattleResources - > bufferB [ gBattlerAttacker ] [ 1 ] - 1 ;
gLastUsedItem = gBattleResources - > bufferB [ gBattlerAttacker ] [ 2 ] ;
2020-09-08 22:44:04 +02:00
if ( gBattleResults . pokeblockThrows < 0xFF )
gBattleResults . pokeblockThrows + + ;
if ( gBattleStruct - > safariPkblThrowCounter < 3 )
gBattleStruct - > safariPkblThrowCounter + + ;
if ( gBattleStruct - > safariEscapeFactor > 1 )
{
2020-12-13 05:28:01 +01:00
// BUG: safariEscapeFactor can become 0 below. This causes the pokeblock throw glitch.
# ifdef BUGFIX
if ( gBattleStruct - > safariEscapeFactor < = sPkblToEscapeFactor [ gBattleStruct - > safariPkblThrowCounter ] [ gBattleCommunication [ MULTISTRING_CHOOSER ] ] )
# else
2020-09-08 22:44:04 +02:00
if ( gBattleStruct - > safariEscapeFactor < sPkblToEscapeFactor [ gBattleStruct - > safariPkblThrowCounter ] [ gBattleCommunication [ MULTISTRING_CHOOSER ] ] )
2020-12-13 05:28:01 +01:00
# endif
2020-09-08 22:44:04 +02:00
gBattleStruct - > safariEscapeFactor = 1 ;
else
gBattleStruct - > safariEscapeFactor - = sPkblToEscapeFactor [ gBattleStruct - > safariPkblThrowCounter ] [ gBattleCommunication [ MULTISTRING_CHOOSER ] ] ;
}
gBattlescriptCurrInstr = gBattlescriptsForSafariActions [ 2 ] ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
void HandleAction_GoNear ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gBattleStruct - > safariCatchFactor + = sGoNearCounterToCatchFactor [ gBattleStruct - > safariGoNearCounter ] ;
if ( gBattleStruct - > safariCatchFactor > 20 )
gBattleStruct - > safariCatchFactor = 20 ;
gBattleStruct - > safariEscapeFactor + = sGoNearCounterToEscapeFactor [ gBattleStruct - > safariGoNearCounter ] ;
if ( gBattleStruct - > safariEscapeFactor > 20 )
gBattleStruct - > safariEscapeFactor = 20 ;
if ( gBattleStruct - > safariGoNearCounter < 3 )
{
gBattleStruct - > safariGoNearCounter + + ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CREPT_CLOSER ;
2020-09-08 22:44:04 +02:00
}
else
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CANT_GET_CLOSER ;
2020-09-08 22:44:04 +02:00
}
gBattlescriptCurrInstr = gBattlescriptsForSafariActions [ 1 ] ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
}
void HandleAction_SafariZoneRun ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
PlaySE ( SE_FLEE ) ;
gCurrentTurnActionNumber = gBattlersCount ;
gBattleOutcome = B_OUTCOME_RAN ;
}
void HandleAction_WallyBallThrow ( void )
{
gBattlerAttacker = gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
PREPARE_MON_NICK_BUFFER ( gBattleTextBuff1 , gBattlerAttacker , gBattlerPartyIndexes [ gBattlerAttacker ] )
gBattlescriptCurrInstr = gBattlescriptsForSafariActions [ 3 ] ;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT ;
gActionsByTurnOrder [ 1 ] = B_ACTION_FINISHED ;
}
void HandleAction_TryFinish ( void )
{
if ( ! HandleFaintedMonActions ( ) )
{
gBattleStruct - > faintedActionsState = 0 ;
gCurrentActionFuncId = B_ACTION_FINISHED ;
}
}
void HandleAction_NothingIsFainted ( void )
{
gCurrentTurnActionNumber + + ;
gCurrentActionFuncId = gActionsByTurnOrder [ gCurrentTurnActionNumber ] ;
gHitMarker & = ~ ( HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
2021-10-29 15:03:14 +02:00
| HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_PASSIVE_DAMAGE
2020-09-08 22:44:04 +02:00
| HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
| HITMARKER_CHARGING | HITMARKER_x4000000 ) ;
}
void HandleAction_ActionFinished ( void )
{
* ( gBattleStruct - > monToSwitchIntoId + gBattlerByTurnOrder [ gCurrentTurnActionNumber ] ) = 6 ;
gCurrentTurnActionNumber + + ;
gCurrentActionFuncId = gActionsByTurnOrder [ gCurrentTurnActionNumber ] ;
SpecialStatusesClear ( ) ;
gHitMarker & = ~ ( HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
2021-10-29 15:03:14 +02:00
| HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_PASSIVE_DAMAGE
2020-09-08 22:44:04 +02:00
| HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
2021-09-06 08:27:42 +02:00
| HITMARKER_CHARGING | HITMARKER_x4000000 | HITMARKER_IGNORE_DISGUISE ) ;
2020-09-08 22:44:04 +02:00
gCurrentMove = 0 ;
gBattleMoveDamage = 0 ;
gMoveResultFlags = 0 ;
gBattleScripting . animTurn = 0 ;
gBattleScripting . animTargetsHit = 0 ;
gLastLandedMoves [ gBattlerAttacker ] = 0 ;
gLastHitByType [ gBattlerAttacker ] = 0 ;
gBattleStruct - > dynamicMoveType = 0 ;
2020-10-11 06:57:16 +02:00
gBattleScripting . moveendState = 0 ;
2020-09-08 22:44:04 +02:00
gBattleScripting . moveendState = 0 ;
gBattleCommunication [ 3 ] = 0 ;
gBattleCommunication [ 4 ] = 0 ;
gBattleScripting . multihitMoveEffect = 0 ;
gBattleResources - > battleScriptsStack - > size = 0 ;
}
2017-10-06 17:06:45 +02:00
2017-10-06 19:09:37 +02:00
// rom const data
2021-04-04 02:55:49 +02:00
static const u8 sMovesNotAffectedByStench [ ] =
{
[ MOVE_AIR_SLASH ] = 1 ,
[ MOVE_ASTONISH ] = 1 ,
[ MOVE_BITE ] = 1 ,
[ MOVE_BONE_CLUB ] = 1 ,
[ MOVE_DARK_PULSE ] = 1 ,
[ MOVE_DOUBLE_IRON_BASH ] = 1 ,
[ MOVE_DRAGON_RUSH ] = 1 ,
[ MOVE_EXTRASENSORY ] = 1 ,
[ MOVE_FAKE_OUT ] = 1 ,
[ MOVE_FIERY_WRATH ] = 1 ,
[ MOVE_FIRE_FANG ] = 1 ,
[ MOVE_FLING ] = 1 ,
[ MOVE_FLOATY_FALL ] = 1 ,
[ MOVE_HEADBUTT ] = 1 ,
[ MOVE_HEART_STAMP ] = 1 ,
[ MOVE_HYPER_FANG ] = 1 ,
[ MOVE_ICE_FANG ] = 1 ,
[ MOVE_ICICLE_CRASH ] = 1 ,
[ MOVE_IRON_HEAD ] = 1 ,
[ MOVE_NEEDLE_ARM ] = 1 ,
[ MOVE_NONE ] = 1 ,
[ MOVE_ROCK_SLIDE ] = 1 ,
[ MOVE_ROLLING_KICK ] = 1 ,
[ MOVE_SECRET_POWER ] = 1 ,
[ MOVE_SKY_ATTACK ] = 1 ,
[ MOVE_SNORE ] = 1 ,
[ MOVE_STEAMROLLER ] = 1 ,
[ MOVE_STOMP ] = 1 ,
[ MOVE_THUNDER_FANG ] = 1 ,
[ MOVE_TWISTER ] = 1 ,
[ MOVE_WATERFALL ] = 1 ,
[ MOVE_ZEN_HEADBUTT ] = 1 ,
[ MOVE_ZING_ZAP ] = 1 ,
} ;
2018-07-14 18:58:45 +02:00
static const u8 sAbilitiesAffectedByMoldBreaker [ ] =
{
[ ABILITY_BATTLE_ARMOR ] = 1 ,
[ ABILITY_CLEAR_BODY ] = 1 ,
[ ABILITY_DAMP ] = 1 ,
[ ABILITY_DRY_SKIN ] = 1 ,
[ ABILITY_FILTER ] = 1 ,
[ ABILITY_FLASH_FIRE ] = 1 ,
[ ABILITY_FLOWER_GIFT ] = 1 ,
[ ABILITY_HEATPROOF ] = 1 ,
[ ABILITY_HYPER_CUTTER ] = 1 ,
[ ABILITY_IMMUNITY ] = 1 ,
[ ABILITY_INNER_FOCUS ] = 1 ,
[ ABILITY_INSOMNIA ] = 1 ,
[ ABILITY_KEEN_EYE ] = 1 ,
[ ABILITY_LEAF_GUARD ] = 1 ,
[ ABILITY_LEVITATE ] = 1 ,
[ ABILITY_LIGHTNING_ROD ] = 1 ,
[ ABILITY_LIMBER ] = 1 ,
[ ABILITY_MAGMA_ARMOR ] = 1 ,
[ ABILITY_MARVEL_SCALE ] = 1 ,
[ ABILITY_MOTOR_DRIVE ] = 1 ,
[ ABILITY_OBLIVIOUS ] = 1 ,
[ ABILITY_OWN_TEMPO ] = 1 ,
[ ABILITY_SAND_VEIL ] = 1 ,
[ ABILITY_SHELL_ARMOR ] = 1 ,
[ ABILITY_SHIELD_DUST ] = 1 ,
[ ABILITY_SIMPLE ] = 1 ,
[ ABILITY_SNOW_CLOAK ] = 1 ,
[ ABILITY_SOLID_ROCK ] = 1 ,
[ ABILITY_SOUNDPROOF ] = 1 ,
[ ABILITY_STICKY_HOLD ] = 1 ,
[ ABILITY_STORM_DRAIN ] = 1 ,
[ ABILITY_STURDY ] = 1 ,
[ ABILITY_SUCTION_CUPS ] = 1 ,
[ ABILITY_TANGLED_FEET ] = 1 ,
[ ABILITY_THICK_FAT ] = 1 ,
[ ABILITY_UNAWARE ] = 1 ,
[ ABILITY_VITAL_SPIRIT ] = 1 ,
[ ABILITY_VOLT_ABSORB ] = 1 ,
[ ABILITY_WATER_ABSORB ] = 1 ,
[ ABILITY_WATER_VEIL ] = 1 ,
[ ABILITY_WHITE_SMOKE ] = 1 ,
[ ABILITY_WONDER_GUARD ] = 1 ,
[ ABILITY_BIG_PECKS ] = 1 ,
[ ABILITY_CONTRARY ] = 1 ,
[ ABILITY_FRIEND_GUARD ] = 1 ,
[ ABILITY_HEAVY_METAL ] = 1 ,
[ ABILITY_LIGHT_METAL ] = 1 ,
[ ABILITY_MAGIC_BOUNCE ] = 1 ,
[ ABILITY_MULTISCALE ] = 1 ,
[ ABILITY_SAP_SIPPER ] = 1 ,
[ ABILITY_TELEPATHY ] = 1 ,
[ ABILITY_WONDER_SKIN ] = 1 ,
[ ABILITY_AROMA_VEIL ] = 1 ,
[ ABILITY_BULLETPROOF ] = 1 ,
[ ABILITY_FLOWER_VEIL ] = 1 ,
[ ABILITY_FUR_COAT ] = 1 ,
[ ABILITY_OVERCOAT ] = 1 ,
[ ABILITY_SWEET_VEIL ] = 1 ,
[ ABILITY_DAZZLING ] = 1 ,
[ ABILITY_DISGUISE ] = 1 ,
[ ABILITY_FLUFFY ] = 1 ,
[ ABILITY_QUEENLY_MAJESTY ] = 1 ,
[ ABILITY_WATER_BUBBLE ] = 1 ,
2021-10-02 22:07:29 +02:00
[ ABILITY_MIRROR_ARMOR ] = 1 ,
[ ABILITY_PUNK_ROCK ] = 1 ,
[ ABILITY_ICE_SCALES ] = 1 ,
[ ABILITY_ICE_FACE ] = 1 ,
[ ABILITY_PASTEL_VEIL ] = 1 ,
2018-07-14 18:58:45 +02:00
} ;
2020-02-17 10:59:39 +01:00
static const u8 sAbilitiesNotTraced [ ABILITIES_COUNT ] =
{
2021-01-25 19:37:11 +01:00
[ ABILITY_AS_ONE_ICE_RIDER ] = 1 ,
[ ABILITY_AS_ONE_SHADOW_RIDER ] = 1 ,
2020-02-17 10:59:39 +01:00
[ ABILITY_BATTLE_BOND ] = 1 ,
[ ABILITY_COMATOSE ] = 1 ,
[ ABILITY_DISGUISE ] = 1 ,
[ ABILITY_FLOWER_GIFT ] = 1 ,
[ ABILITY_FORECAST ] = 1 ,
2021-01-25 18:55:51 +01:00
[ ABILITY_GULP_MISSILE ] = 1 ,
[ ABILITY_HUNGER_SWITCH ] = 1 ,
[ ABILITY_ICE_FACE ] = 1 ,
2020-02-17 10:59:39 +01:00
[ ABILITY_ILLUSION ] = 1 ,
[ ABILITY_IMPOSTER ] = 1 ,
[ ABILITY_MULTITYPE ] = 1 ,
2021-01-25 18:55:51 +01:00
[ ABILITY_NEUTRALIZING_GAS ] = 1 ,
2020-02-17 10:59:39 +01:00
[ ABILITY_NONE ] = 1 ,
[ ABILITY_POWER_CONSTRUCT ] = 1 ,
[ ABILITY_POWER_OF_ALCHEMY ] = 1 ,
[ ABILITY_RECEIVER ] = 1 ,
[ ABILITY_RKS_SYSTEM ] = 1 ,
[ ABILITY_SCHOOLING ] = 1 ,
[ ABILITY_SHIELDS_DOWN ] = 1 ,
[ ABILITY_STANCE_CHANGE ] = 1 ,
[ ABILITY_TRACE ] = 1 ,
[ ABILITY_ZEN_MODE ] = 1 ,
} ;
2018-07-14 18:58:45 +02:00
static const u8 sHoldEffectToType [ ] [ 2 ] =
{
{ HOLD_EFFECT_BUG_POWER , TYPE_BUG } ,
{ HOLD_EFFECT_STEEL_POWER , TYPE_STEEL } ,
{ HOLD_EFFECT_GROUND_POWER , TYPE_GROUND } ,
{ HOLD_EFFECT_ROCK_POWER , TYPE_ROCK } ,
{ HOLD_EFFECT_GRASS_POWER , TYPE_GRASS } ,
{ HOLD_EFFECT_DARK_POWER , TYPE_DARK } ,
{ HOLD_EFFECT_FIGHTING_POWER , TYPE_FIGHTING } ,
{ HOLD_EFFECT_ELECTRIC_POWER , TYPE_ELECTRIC } ,
{ HOLD_EFFECT_WATER_POWER , TYPE_WATER } ,
{ HOLD_EFFECT_FLYING_POWER , TYPE_FLYING } ,
{ HOLD_EFFECT_POISON_POWER , TYPE_POISON } ,
{ HOLD_EFFECT_ICE_POWER , TYPE_ICE } ,
{ HOLD_EFFECT_GHOST_POWER , TYPE_GHOST } ,
{ HOLD_EFFECT_PSYCHIC_POWER , TYPE_PSYCHIC } ,
{ HOLD_EFFECT_FIRE_POWER , TYPE_FIRE } ,
{ HOLD_EFFECT_DRAGON_POWER , TYPE_DRAGON } ,
{ HOLD_EFFECT_NORMAL_POWER , TYPE_NORMAL } ,
{ HOLD_EFFECT_FAIRY_POWER , TYPE_FAIRY } ,
} ;
2018-07-14 22:56:03 +02:00
// percent in UQ_4_12 format
static const u16 sPercentToModifier [ ] =
{
UQ_4_12 ( 0.00 ) , // 0
UQ_4_12 ( 0.01 ) , // 1
UQ_4_12 ( 0.02 ) , // 2
UQ_4_12 ( 0.03 ) , // 3
UQ_4_12 ( 0.04 ) , // 4
UQ_4_12 ( 0.05 ) , // 5
UQ_4_12 ( 0.06 ) , // 6
UQ_4_12 ( 0.07 ) , // 7
UQ_4_12 ( 0.08 ) , // 8
UQ_4_12 ( 0.09 ) , // 9
UQ_4_12 ( 0.10 ) , // 10
UQ_4_12 ( 0.11 ) , // 11
UQ_4_12 ( 0.12 ) , // 12
UQ_4_12 ( 0.13 ) , // 13
UQ_4_12 ( 0.14 ) , // 14
UQ_4_12 ( 0.15 ) , // 15
UQ_4_12 ( 0.16 ) , // 16
UQ_4_12 ( 0.17 ) , // 17
UQ_4_12 ( 0.18 ) , // 18
UQ_4_12 ( 0.19 ) , // 19
UQ_4_12 ( 0.20 ) , // 20
UQ_4_12 ( 0.21 ) , // 21
UQ_4_12 ( 0.22 ) , // 22
UQ_4_12 ( 0.23 ) , // 23
UQ_4_12 ( 0.24 ) , // 24
UQ_4_12 ( 0.25 ) , // 25
UQ_4_12 ( 0.26 ) , // 26
UQ_4_12 ( 0.27 ) , // 27
UQ_4_12 ( 0.28 ) , // 28
UQ_4_12 ( 0.29 ) , // 29
UQ_4_12 ( 0.30 ) , // 30
UQ_4_12 ( 0.31 ) , // 31
UQ_4_12 ( 0.32 ) , // 32
UQ_4_12 ( 0.33 ) , // 33
UQ_4_12 ( 0.34 ) , // 34
UQ_4_12 ( 0.35 ) , // 35
UQ_4_12 ( 0.36 ) , // 36
UQ_4_12 ( 0.37 ) , // 37
UQ_4_12 ( 0.38 ) , // 38
UQ_4_12 ( 0.39 ) , // 39
UQ_4_12 ( 0.40 ) , // 40
UQ_4_12 ( 0.41 ) , // 41
UQ_4_12 ( 0.42 ) , // 42
UQ_4_12 ( 0.43 ) , // 43
UQ_4_12 ( 0.44 ) , // 44
UQ_4_12 ( 0.45 ) , // 45
UQ_4_12 ( 0.46 ) , // 46
UQ_4_12 ( 0.47 ) , // 47
UQ_4_12 ( 0.48 ) , // 48
UQ_4_12 ( 0.49 ) , // 49
UQ_4_12 ( 0.50 ) , // 50
UQ_4_12 ( 0.51 ) , // 51
UQ_4_12 ( 0.52 ) , // 52
UQ_4_12 ( 0.53 ) , // 53
UQ_4_12 ( 0.54 ) , // 54
UQ_4_12 ( 0.55 ) , // 55
UQ_4_12 ( 0.56 ) , // 56
UQ_4_12 ( 0.57 ) , // 57
UQ_4_12 ( 0.58 ) , // 58
UQ_4_12 ( 0.59 ) , // 59
UQ_4_12 ( 0.60 ) , // 60
UQ_4_12 ( 0.61 ) , // 61
UQ_4_12 ( 0.62 ) , // 62
UQ_4_12 ( 0.63 ) , // 63
UQ_4_12 ( 0.64 ) , // 64
UQ_4_12 ( 0.65 ) , // 65
UQ_4_12 ( 0.66 ) , // 66
UQ_4_12 ( 0.67 ) , // 67
UQ_4_12 ( 0.68 ) , // 68
UQ_4_12 ( 0.69 ) , // 69
UQ_4_12 ( 0.70 ) , // 70
UQ_4_12 ( 0.71 ) , // 71
UQ_4_12 ( 0.72 ) , // 72
UQ_4_12 ( 0.73 ) , // 73
UQ_4_12 ( 0.74 ) , // 74
UQ_4_12 ( 0.75 ) , // 75
UQ_4_12 ( 0.76 ) , // 76
UQ_4_12 ( 0.77 ) , // 77
UQ_4_12 ( 0.78 ) , // 78
UQ_4_12 ( 0.79 ) , // 79
UQ_4_12 ( 0.80 ) , // 80
UQ_4_12 ( 0.81 ) , // 81
UQ_4_12 ( 0.82 ) , // 82
UQ_4_12 ( 0.83 ) , // 83
UQ_4_12 ( 0.84 ) , // 84
UQ_4_12 ( 0.85 ) , // 85
UQ_4_12 ( 0.86 ) , // 86
UQ_4_12 ( 0.87 ) , // 87
UQ_4_12 ( 0.88 ) , // 88
UQ_4_12 ( 0.89 ) , // 89
UQ_4_12 ( 0.90 ) , // 90
UQ_4_12 ( 0.91 ) , // 91
UQ_4_12 ( 0.92 ) , // 92
UQ_4_12 ( 0.93 ) , // 93
UQ_4_12 ( 0.94 ) , // 94
UQ_4_12 ( 0.95 ) , // 95
UQ_4_12 ( 0.96 ) , // 96
UQ_4_12 ( 0.97 ) , // 97
UQ_4_12 ( 0.98 ) , // 98
UQ_4_12 ( 0.99 ) , // 99
UQ_4_12 ( 1.00 ) , // 100
} ;
# define X UQ_4_12
static const u16 sTypeEffectivenessTable [ NUMBER_OF_MON_TYPES ] [ NUMBER_OF_MON_TYPES ] =
{
// normal fight flying poison ground rock bug ghost steel mystery fire water grass electric psychic ice dragon dark fairy
2020-10-19 23:01:19 +02:00
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // normal
{ X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 0.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) } , // fight
{ X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // flying
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) } , // poison
{ X ( 1.0 ) , X ( 1.0 ) , X ( 0.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // ground
{ X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // rock
{ X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) } , // bug
2020-11-11 21:48:02 +01:00
# if B_STEEL_RESISTANCES >= GEN_6
2020-10-19 23:01:19 +02:00
{ X ( 0.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) } , // ghost
2020-11-11 21:48:02 +01:00
# else
{ X ( 0.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) } , // ghost
# endif
2020-10-19 23:01:19 +02:00
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) } , // steel
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // mystery
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) } , // fire
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) } , // water
{ X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) } , // grass
{ X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) } , // electric
{ X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.0 ) , X ( 1.0 ) } , // psychic
{ X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // ice
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.0 ) } , // dragon
2020-11-11 21:48:02 +01:00
# if B_STEEL_RESISTANCES >= GEN_6
2020-10-19 23:01:19 +02:00
{ X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) } , // dark
2020-11-11 21:48:02 +01:00
# else
{ X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) } , // dark
# endif
2020-10-19 23:01:19 +02:00
{ X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) } , // fairy
2018-07-14 22:56:03 +02:00
} ;
2020-07-17 20:53:22 +02:00
static const u16 sInverseTypeEffectivenessTable [ NUMBER_OF_MON_TYPES ] [ NUMBER_OF_MON_TYPES ] =
2017-10-06 19:09:37 +02:00
{
2020-07-17 20:53:22 +02:00
// normal fight flying poison ground rock bug ghost steel mystery fire water grass electric psychic ice dragon dark fairy
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // normal
{ X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) } , // fight
{ X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // flying
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) } , // poison
{ X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // ground
{ X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // rock
{ X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) } , // bug
2020-11-11 21:48:02 +01:00
# if B_STEEL_RESISTANCES >= GEN_6
2020-07-17 20:53:22 +02:00
{ X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) } , // ghost
2020-11-11 21:48:02 +01:00
# else
{ X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) } , // ghost
# endif
2020-07-17 20:53:22 +02:00
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) } , // steel
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // mystery
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // fire
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // water
{ X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // grass
{ X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) } , // electric
{ X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) } , // psychic
{ X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) } , // ice
{ X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) } , // dragon
2020-11-11 21:48:02 +01:00
# if B_STEEL_RESISTANCES >= GEN_6
2020-07-17 20:53:22 +02:00
{ X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) } , // dark
2020-11-11 21:48:02 +01:00
# else
{ X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 2.0 ) } , // dark
# endif
2020-07-17 20:53:22 +02:00
{ X ( 1.0 ) , X ( 0.5 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 2.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 1.0 ) , X ( 0.5 ) , X ( 0.5 ) , X ( 1.0 ) } , // fairy
2017-10-06 19:09:37 +02:00
} ;
2018-07-14 22:56:03 +02:00
# undef X
2018-07-14 18:58:45 +02:00
// code
2018-02-08 11:17:41 +01:00
u8 GetBattlerForBattleScript ( u8 caseId )
2017-10-06 17:06:45 +02:00
{
u8 ret = 0 ;
switch ( caseId )
{
2018-02-08 11:17:41 +01:00
case BS_TARGET :
2018-02-06 23:09:39 +01:00
ret = gBattlerTarget ;
2017-10-06 17:06:45 +02:00
break ;
2018-02-08 11:17:41 +01:00
case BS_ATTACKER :
2018-02-06 23:09:39 +01:00
ret = gBattlerAttacker ;
2017-10-06 17:06:45 +02:00
break ;
2018-02-08 11:17:41 +01:00
case BS_EFFECT_BATTLER :
ret = gEffectBattler ;
2017-10-06 17:06:45 +02:00
break ;
2018-07-01 11:15:42 +02:00
case BS_BATTLER_0 :
2017-10-06 17:06:45 +02:00
ret = 0 ;
break ;
2018-02-08 11:17:41 +01:00
case BS_SCRIPTING :
2018-02-06 02:46:59 +01:00
ret = gBattleScripting . battler ;
2017-10-06 17:06:45 +02:00
break ;
2018-02-08 11:17:41 +01:00
case BS_FAINTED :
ret = gBattlerFainted ;
2017-10-06 17:06:45 +02:00
break ;
case 5 :
2018-02-08 11:17:41 +01:00
ret = gBattlerFainted ;
2017-10-06 17:06:45 +02:00
break ;
case 4 :
case 6 :
case 8 :
case 9 :
2018-02-08 11:17:41 +01:00
case BS_PLAYER1 :
2018-02-06 02:46:59 +01:00
ret = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-10-06 17:06:45 +02:00
break ;
2018-02-08 11:17:41 +01:00
case BS_OPPONENT1 :
2018-02-06 02:46:59 +01:00
ret = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
2017-10-06 17:06:45 +02:00
break ;
2018-02-08 11:17:41 +01:00
case BS_PLAYER2 :
2018-02-06 02:46:59 +01:00
ret = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
2017-10-06 17:06:45 +02:00
break ;
2018-02-08 11:17:41 +01:00
case BS_OPPONENT2 :
2018-02-06 02:46:59 +01:00
ret = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
2017-10-06 17:06:45 +02:00
break ;
2018-09-29 13:36:33 +02:00
case BS_ABILITY_BATTLER :
ret = gBattlerAbility ;
2020-04-22 14:40:44 +02:00
break ;
2017-10-06 17:06:45 +02:00
}
return ret ;
}
2019-01-19 22:32:25 +01:00
void PressurePPLose ( u8 target , u8 attacker , u16 move )
2017-10-06 17:06:45 +02:00
{
2019-01-19 22:32:25 +01:00
int moveIndex ;
2017-10-06 17:06:45 +02:00
2021-10-02 23:31:09 +02:00
if ( GetBattlerAbility ( target ) ! = ABILITY_PRESSURE )
2017-10-06 17:06:45 +02:00
return ;
2019-01-19 22:32:25 +01:00
for ( moveIndex = 0 ; moveIndex < MAX_MON_MOVES ; moveIndex + + )
2017-10-06 17:06:45 +02:00
{
2019-01-19 22:32:25 +01:00
if ( gBattleMons [ attacker ] . moves [ moveIndex ] = = move )
2017-10-06 17:06:45 +02:00
break ;
}
2019-01-19 22:32:25 +01:00
if ( moveIndex = = MAX_MON_MOVES )
2017-10-06 17:06:45 +02:00
return ;
2019-01-19 22:32:25 +01:00
if ( gBattleMons [ attacker ] . pp [ moveIndex ] ! = 0 )
gBattleMons [ attacker ] . pp [ moveIndex ] - - ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
if ( ! ( gBattleMons [ attacker ] . status2 & STATUS2_TRANSFORMED )
2019-01-19 22:32:25 +01:00
& & ! ( gDisableStructs [ attacker ] . mimickedMoves & gBitTable [ moveIndex ] ) )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
gActiveBattler = attacker ;
2019-01-19 22:32:25 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_PPMOVE1_BATTLE + moveIndex , 0 , 1 , & gBattleMons [ gActiveBattler ] . pp [ moveIndex ] ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-06 17:06:45 +02:00
}
}
2019-03-02 23:40:38 +01:00
void PressurePPLoseOnUsingImprison ( u8 attacker )
2017-10-06 17:06:45 +02:00
{
2019-01-19 22:32:25 +01:00
int i , j ;
2019-03-02 23:40:38 +01:00
int imprisonPos = 4 ;
2018-02-06 02:46:59 +01:00
u8 atkSide = GetBattlerSide ( attacker ) ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-06 17:06:45 +02:00
{
2021-10-02 23:31:09 +02:00
if ( atkSide ! = GetBattlerSide ( i ) & & GetBattlerAbility ( i ) = = ABILITY_PRESSURE )
2017-10-06 17:06:45 +02:00
{
2018-12-25 18:50:15 +01:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . moves [ j ] = = MOVE_IMPRISON )
2017-10-06 17:06:45 +02:00
break ;
}
2018-12-25 18:50:15 +01:00
if ( j ! = MAX_MON_MOVES )
2017-10-06 17:06:45 +02:00
{
2019-03-02 23:40:38 +01:00
imprisonPos = j ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . pp [ j ] ! = 0 )
gBattleMons [ attacker ] . pp [ j ] - - ;
2017-10-06 17:06:45 +02:00
}
}
}
2019-03-02 23:40:38 +01:00
if ( imprisonPos ! = 4
2018-02-06 02:46:59 +01:00
& & ! ( gBattleMons [ attacker ] . status2 & STATUS2_TRANSFORMED )
2019-03-02 23:40:38 +01:00
& & ! ( gDisableStructs [ attacker ] . mimickedMoves & gBitTable [ imprisonPos ] ) )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
gActiveBattler = attacker ;
2019-03-02 23:40:38 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_PPMOVE1_BATTLE + imprisonPos , 0 , 1 , & gBattleMons [ gActiveBattler ] . pp [ imprisonPos ] ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-06 17:06:45 +02:00
}
}
2018-02-06 02:46:59 +01:00
void PressurePPLoseOnUsingPerishSong ( u8 attacker )
2017-10-06 17:06:45 +02:00
{
2019-01-19 22:32:25 +01:00
int i , j ;
int perishSongPos = 4 ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-06 17:06:45 +02:00
{
2021-10-02 23:31:09 +02:00
if ( GetBattlerAbility ( i ) = = ABILITY_PRESSURE & & i ! = attacker )
2017-10-06 17:06:45 +02:00
{
2018-12-25 18:50:15 +01:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . moves [ j ] = = MOVE_PERISH_SONG )
2017-10-06 17:06:45 +02:00
break ;
}
2018-12-25 18:50:15 +01:00
if ( j ! = MAX_MON_MOVES )
2017-10-06 17:06:45 +02:00
{
perishSongPos = j ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . pp [ j ] ! = 0 )
gBattleMons [ attacker ] . pp [ j ] - - ;
2017-10-06 17:06:45 +02:00
}
}
}
2018-12-25 18:50:15 +01:00
if ( perishSongPos ! = MAX_MON_MOVES
2018-02-06 02:46:59 +01:00
& & ! ( gBattleMons [ attacker ] . status2 & STATUS2_TRANSFORMED )
2019-01-19 22:32:25 +01:00
& & ! ( gDisableStructs [ attacker ] . mimickedMoves & gBitTable [ perishSongPos ] ) )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
gActiveBattler = attacker ;
2018-02-06 20:48:02 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_PPMOVE1_BATTLE + perishSongPos , 0 , 1 , & gBattleMons [ gActiveBattler ] . pp [ perishSongPos ] ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-06 17:06:45 +02:00
}
}
2018-02-06 20:48:02 +01:00
void MarkAllBattlersForControllerExec ( void ) // unused
2017-10-06 17:06:45 +02:00
{
2019-01-19 22:32:25 +01:00
int i ;
2017-10-06 17:06:45 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2021-03-30 23:38:09 +02:00
gBattleControllerExecFlags | = gBitTable [ i ] < < ( 32 - MAX_BATTLERS_COUNT ) ;
2017-10-06 17:06:45 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2018-02-06 20:48:02 +01:00
gBattleControllerExecFlags | = gBitTable [ i ] ;
2017-10-06 17:06:45 +02:00
}
}
2018-12-23 18:47:00 +01:00
bool32 IsBattlerMarkedForControllerExec ( u8 battlerId )
{
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
return ( gBattleControllerExecFlags & ( gBitTable [ battlerId ] < < 0x1C ) ) ! = 0 ;
else
return ( gBattleControllerExecFlags & ( gBitTable [ battlerId ] ) ) ! = 0 ;
}
2018-02-06 20:48:02 +01:00
void MarkBattlerForControllerExec ( u8 battlerId )
2017-10-06 17:06:45 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
2021-03-30 23:38:09 +02:00
gBattleControllerExecFlags | = gBitTable [ battlerId ] < < ( 32 - MAX_BATTLERS_COUNT ) ;
2017-10-06 17:06:45 +02:00
else
2018-02-06 20:48:02 +01:00
gBattleControllerExecFlags | = gBitTable [ battlerId ] ;
2017-10-06 17:06:45 +02:00
}
2021-01-22 08:48:22 +01:00
void MarkBattlerReceivedLinkData ( u8 battlerId )
2017-10-06 17:06:45 +02:00
{
s32 i ;
2017-10-13 17:09:36 +02:00
for ( i = 0 ; i < GetLinkPlayerCount ( ) ; i + + )
2021-01-22 08:48:22 +01:00
gBattleControllerExecFlags | = gBitTable [ battlerId ] < < ( i < < 2 ) ;
2017-10-06 17:06:45 +02:00
2021-01-22 08:48:22 +01:00
gBattleControllerExecFlags & = ~ ( 0x10000000 < < battlerId ) ;
2017-10-06 17:06:45 +02:00
}
2018-02-06 02:46:59 +01:00
void CancelMultiTurnMoves ( u8 battler )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_MULTIPLETURNS ) ;
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_LOCK_CONFUSE ) ;
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_UPROAR ) ;
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_BIDE ) ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
gStatuses3 [ battler ] & = ~ ( STATUS3_SEMI_INVULNERABLE ) ;
2017-10-06 17:06:45 +02:00
2018-10-14 18:10:54 +02:00
gDisableStructs [ battler ] . rolloutTimer = 0 ;
2018-02-06 02:46:59 +01:00
gDisableStructs [ battler ] . furyCutterCounter = 0 ;
2017-10-06 17:06:45 +02:00
}
2018-02-06 02:46:59 +01:00
bool8 WasUnableToUseMove ( u8 battler )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gProtectStructs [ battler ] . prlzImmobility
2019-03-02 23:40:38 +01:00
| | gProtectStructs [ battler ] . usedImprisonedMove
2018-02-06 02:46:59 +01:00
| | gProtectStructs [ battler ] . loveImmobility
| | gProtectStructs [ battler ] . usedDisabledMove
| | gProtectStructs [ battler ] . usedTauntedMove
2018-08-02 21:27:28 +02:00
| | gProtectStructs [ battler ] . usedGravityPreventedMove
| | gProtectStructs [ battler ] . usedHealBlockedMove
2018-02-06 02:46:59 +01:00
| | gProtectStructs [ battler ] . flag2Unknown
| | gProtectStructs [ battler ] . flinchImmobility
2018-12-03 12:50:32 +01:00
| | gProtectStructs [ battler ] . confusionSelfDmg
2019-04-16 15:01:48 +02:00
| | gProtectStructs [ battler ] . powderSelfDmg
| | gProtectStructs [ battler ] . usedThroatChopPreventedMove )
2017-10-06 17:06:45 +02:00
return TRUE ;
else
return FALSE ;
}
2018-02-06 02:46:59 +01:00
void PrepareStringBattle ( u16 stringId , u8 battler )
2017-10-06 17:06:45 +02:00
{
2021-11-23 10:54:30 +01:00
u32 targetSide = GetBattlerSide ( gBattlerTarget ) ;
2018-12-26 19:12:07 +01:00
// Support for Contrary ability.
// If a move attempted to raise stat - print "won't increase".
// If a move attempted to lower stat - print "won't decrease".
if ( stringId = = STRINGID_STATSWONTDECREASE & & ! ( gBattleScripting . statChanger & STAT_BUFF_NEGATIVE ) )
stringId = STRINGID_STATSWONTINCREASE ;
else if ( stringId = = STRINGID_STATSWONTINCREASE & & gBattleScripting . statChanger & STAT_BUFF_NEGATIVE )
stringId = STRINGID_STATSWONTDECREASE ;
2019-02-16 12:54:11 +01:00
else if ( stringId = = STRINGID_STATSWONTDECREASE2 & & GetBattlerAbility ( battler ) = = ABILITY_CONTRARY )
2018-12-26 19:12:07 +01:00
stringId = STRINGID_STATSWONTINCREASE2 ;
else if ( stringId = = STRINGID_STATSWONTINCREASE2 & & GetBattlerAbility ( battler ) = = ABILITY_CONTRARY )
stringId = STRINGID_STATSWONTDECREASE2 ;
2019-02-16 12:54:11 +01:00
// Check Defiant and Competitive stat raise whenever a stat is lowered.
2021-04-28 03:36:37 +02:00
else if ( ( stringId = = STRINGID_DEFENDERSSTATFELL | | stringId = = STRINGID_PKMNCUTSATTACKWITH )
2021-09-03 19:13:02 +02:00
& & ( ( GetBattlerAbility ( gBattlerTarget ) = = ABILITY_DEFIANT & & CompareStat ( gBattlerTarget , STAT_ATK , MAX_STAT_STAGE , CMP_LESS_THAN ) )
| | ( GetBattlerAbility ( gBattlerTarget ) = = ABILITY_COMPETITIVE & & CompareStat ( gBattlerTarget , STAT_SPATK , MAX_STAT_STAGE , CMP_LESS_THAN ) ) )
2020-07-11 12:28:42 +02:00
& & gSpecialStatuses [ gBattlerTarget ] . changedStatsBattlerId ! = BATTLE_PARTNER ( gBattlerTarget )
2021-11-23 10:54:30 +01:00
// && gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) // Why was this here? Needs investigating
& & ! ( gBattleScripting . stickyWebStatDrop = = 1 & & gSideTimers [ targetSide ] . stickyWebBattlerSide = = targetSide ) ) // Sticky Web must have been set by the foe
2019-02-16 12:54:11 +01:00
{
2021-11-23 10:54:30 +01:00
gBattleScripting . stickyWebStatDrop = 0 ;
2019-02-16 12:54:11 +01:00
gBattlerAbility = gBattlerTarget ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_DefiantActivates ;
if ( GetBattlerAbility ( gBattlerTarget ) = = ABILITY_DEFIANT )
SET_STATCHANGER ( STAT_ATK , 2 , FALSE ) ;
else
SET_STATCHANGER ( STAT_SPATK , 2 , FALSE ) ;
}
2018-02-06 02:46:59 +01:00
gActiveBattler = battler ;
2018-02-06 20:48:02 +01:00
BtlController_EmitPrintString ( 0 , stringId ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-06 17:06:45 +02:00
}
void ResetSentPokesToOpponentValue ( void )
{
s32 i ;
u32 bits = 0 ;
gSentPokesToOpponent [ 0 ] = 0 ;
gSentPokesToOpponent [ 1 ] = 0 ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + = 2 )
2018-02-06 20:48:02 +01:00
bits | = gBitTable [ gBattlerPartyIndexes [ i ] ] ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 1 ; i < gBattlersCount ; i + = 2 )
gSentPokesToOpponent [ ( i & BIT_FLANK ) > > 1 ] = bits ;
2017-10-06 17:06:45 +02:00
}
2020-07-28 04:22:16 +02:00
void OpponentSwitchInResetSentPokesToOpponentValue ( u8 battler )
2017-10-06 17:06:45 +02:00
{
s32 i = 0 ;
u32 bits = 0 ;
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( battler ) = = B_SIDE_OPPONENT )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
u8 flank = ( ( battler & BIT_FLANK ) > > 1 ) ;
gSentPokesToOpponent [ flank ] = 0 ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + = 2 )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
if ( ! ( gAbsentBattlerFlags & gBitTable [ i ] ) )
2018-02-06 20:48:02 +01:00
bits | = gBitTable [ gBattlerPartyIndexes [ i ] ] ;
2017-10-06 17:06:45 +02:00
}
2018-02-06 02:46:59 +01:00
gSentPokesToOpponent [ flank ] = bits ;
2017-10-06 17:06:45 +02:00
}
}
2020-07-28 00:10:42 +02:00
void UpdateSentPokesToOpponentValue ( u8 battler )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( battler ) = = B_SIDE_OPPONENT )
2017-10-06 17:06:45 +02:00
{
2020-07-28 04:22:16 +02:00
OpponentSwitchInResetSentPokesToOpponentValue ( battler ) ;
2017-10-06 17:06:45 +02:00
}
else
{
s32 i ;
2018-02-06 02:46:59 +01:00
for ( i = 1 ; i < gBattlersCount ; i + + )
2018-02-06 20:48:02 +01:00
gSentPokesToOpponent [ ( i & BIT_FLANK ) > > 1 ] | = gBitTable [ gBattlerPartyIndexes [ battler ] ] ;
2017-10-06 17:06:45 +02:00
}
}
2017-09-17 14:10:32 +02:00
2018-07-01 11:15:42 +02:00
void BattleScriptPush ( const u8 * bsPtr )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleResources - > battleScriptsStack - > ptr [ gBattleResources - > battleScriptsStack - > size + + ] = bsPtr ;
2017-09-17 14:10:32 +02:00
}
2017-09-22 21:33:49 +02:00
void BattleScriptPushCursor ( void )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleResources - > battleScriptsStack - > ptr [ gBattleResources - > battleScriptsStack - > size + + ] = gBattlescriptCurrInstr ;
2017-09-17 14:10:32 +02:00
}
2017-09-22 21:33:49 +02:00
void BattleScriptPop ( void )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattlescriptCurrInstr = gBattleResources - > battleScriptsStack - > ptr [ - - gBattleResources - > battleScriptsStack - > size ] ;
2017-09-17 14:10:32 +02:00
}
2018-07-31 23:09:47 +02:00
static bool32 IsGravityPreventingMove ( u32 move )
{
if ( ! ( gFieldStatuses & STATUS_FIELD_GRAVITY ) )
return FALSE ;
switch ( move )
{
case MOVE_BOUNCE :
case MOVE_FLY :
case MOVE_FLYING_PRESS :
2021-01-01 00:57:36 +01:00
case MOVE_HIGH_JUMP_KICK :
2018-07-31 23:09:47 +02:00
case MOVE_JUMP_KICK :
case MOVE_MAGNET_RISE :
case MOVE_SKY_DROP :
case MOVE_SPLASH :
case MOVE_TELEKINESIS :
2020-11-13 18:51:50 +01:00
case MOVE_FLOATY_FALL :
2018-07-31 23:09:47 +02:00
return TRUE ;
default :
return FALSE ;
}
}
2020-12-13 23:02:21 +01:00
bool32 IsHealBlockPreventingMove ( u32 battler , u32 move )
2018-07-31 23:09:47 +02:00
{
if ( ! ( gStatuses3 [ battler ] & STATUS3_HEAL_BLOCK ) )
return FALSE ;
2021-06-10 12:55:05 +02:00
2018-07-31 23:09:47 +02:00
switch ( gBattleMoves [ move ] . effect )
{
case EFFECT_ABSORB :
case EFFECT_MORNING_SUN :
case EFFECT_MOONLIGHT :
case EFFECT_RESTORE_HP :
case EFFECT_REST :
case EFFECT_ROOST :
case EFFECT_HEALING_WISH :
case EFFECT_WISH :
2018-11-30 20:48:43 +01:00
case EFFECT_DREAM_EATER :
2018-07-31 23:09:47 +02:00
return TRUE ;
default :
return FALSE ;
}
}
2019-02-01 14:17:24 +01:00
static bool32 IsBelchPreventingMove ( u32 battler , u32 move )
{
if ( gBattleMoves [ move ] . effect ! = EFFECT_BELCH )
return FALSE ;
return ! ( gBattleStruct - > ateBerry [ battler & BIT_SIDE ] & gBitTable [ gBattlerPartyIndexes [ battler ] ] ) ;
}
2017-10-03 21:35:27 +02:00
u8 TrySetCantSelectMoveBattleScript ( void )
2017-09-17 14:10:32 +02:00
{
2019-01-29 22:12:53 +01:00
u32 limitations = 0 ;
2020-10-19 23:01:19 +02:00
u8 moveId = gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] & ~ ( RET_MEGA_EVOLUTION ) ;
2018-09-17 20:37:33 +02:00
u32 move = gBattleMons [ gActiveBattler ] . moves [ moveId ] ;
2018-07-31 23:09:47 +02:00
u32 holdEffect = GetBattlerHoldEffect ( gActiveBattler , TRUE ) ;
2019-01-27 13:52:02 +01:00
u16 * choicedMove = & gBattleStruct - > choicedMove [ gActiveBattler ] ;
2017-09-17 14:10:32 +02:00
2019-01-19 22:32:25 +01:00
if ( gDisableStructs [ gActiveBattler ] . disabledMove = = move & & move ! = MOVE_NONE )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleScripting . battler = gActiveBattler ;
2017-09-17 14:10:32 +02:00
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2018-02-06 02:46:59 +01:00
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingDisabledMoveInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingDisabledMove ;
2018-07-31 23:09:47 +02:00
limitations + + ;
2017-09-17 14:10:32 +02:00
}
}
2018-02-06 02:46:59 +01:00
if ( move = = gLastMoves [ gActiveBattler ] & & move ! = MOVE_STRUGGLE & & ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_TORMENT ) )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
CancelMultiTurnMoves ( gActiveBattler ) ;
2017-09-17 14:10:32 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2018-02-06 02:46:59 +01:00
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingTormentedMoveInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingTormentedMove ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
2018-10-14 18:10:54 +02:00
if ( gDisableStructs [ gActiveBattler ] . tauntTimer ! = 0 & & gBattleMoves [ move ] . power = = 0 )
2017-09-17 14:10:32 +02:00
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2018-02-06 02:46:59 +01:00
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveTauntInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveTaunt ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
2019-04-16 15:01:48 +02:00
if ( gDisableStructs [ gActiveBattler ] . throatChopTimer ! = 0 & & gBattleMoves [ move ] . flags & FLAG_SOUND )
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveThroatChopInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2019-04-16 15:01:48 +02:00
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveThroatChop ;
limitations + + ;
}
}
2018-02-06 02:46:59 +01:00
if ( GetImprisonedMovesCount ( gActiveBattler , move ) )
2017-09-17 14:10:32 +02:00
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2019-03-02 23:40:38 +01:00
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingImprisonedMoveInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2017-09-17 14:10:32 +02:00
}
else
{
2019-03-02 23:40:38 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingImprisonedMove ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
2018-07-31 23:09:47 +02:00
if ( IsGravityPreventingMove ( move ) )
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveGravityInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2018-07-31 23:09:47 +02:00
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveGravity ;
limitations + + ;
}
}
2017-09-17 14:10:32 +02:00
2018-07-31 23:09:47 +02:00
if ( IsHealBlockPreventingMove ( gActiveBattler , move ) )
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveHealBlockInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2018-07-31 23:09:47 +02:00
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveHealBlock ;
limitations + + ;
}
}
2017-09-17 14:10:32 +02:00
2019-02-01 14:17:24 +01:00
if ( IsBelchPreventingMove ( gActiveBattler , move ) )
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedBelchInPalace ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2019-02-01 14:17:24 +01:00
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedBelch ;
limitations + + ;
}
}
2021-07-27 18:31:48 +02:00
if ( move = = MOVE_STUFF_CHEEKS & & ItemId_GetPocket ( gBattleMons [ gActiveBattler ] . item ) ! = POCKET_BERRIES )
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedBelchInPalace ;
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = 1 ;
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedStuffCheeks ;
limitations + + ;
}
}
2017-09-17 14:10:32 +02:00
2018-07-31 23:09:47 +02:00
gPotentialItemEffectBattler = gActiveBattler ;
if ( HOLD_EFFECT_CHOICE ( holdEffect ) & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = move )
2017-09-17 14:10:32 +02:00
{
gCurrentMove = * choicedMove ;
2018-02-06 02:46:59 +01:00
gLastUsedItem = gBattleMons [ gActiveBattler ] . item ;
2017-09-17 14:10:32 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveChoiceItem ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
2021-11-12 23:24:50 +01:00
else if ( holdEffect = = HOLD_EFFECT_ASSAULT_VEST & & gBattleMoves [ move ] . power = = 0 & & move ! = MOVE_ME_FIRST )
2018-07-31 23:09:47 +02:00
{
gCurrentMove = move ;
gLastUsedItem = gBattleMons [ gActiveBattler ] . item ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2018-07-31 23:09:47 +02:00
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveAssaultVest ;
limitations + + ;
}
}
2021-10-30 07:31:44 +02:00
if ( ( GetBattlerAbility ( gActiveBattler ) = = ABILITY_GORILLA_TACTICS ) & & * choicedMove ! = 0
& & * choicedMove ! = 0xFFFF & & * choicedMove ! = move )
{
gCurrentMove = * choicedMove ;
gLastUsedItem = gBattleMons [ gActiveBattler ] . item ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = 1 ;
}
else
{
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingNotAllowedMoveGorillaTactics ;
limitations + + ;
}
}
2017-09-17 14:10:32 +02:00
2018-09-17 20:37:33 +02:00
if ( gBattleMons [ gActiveBattler ] . pp [ moveId ] = = 0 )
2017-09-17 14:10:32 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . palaceUnableToUseMove = TRUE ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingMoveWithNoPP ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
return limitations ;
}
2018-02-08 11:17:41 +01:00
u8 CheckMoveLimitations ( u8 battlerId , u8 unusableMoves , u8 check )
2017-09-17 14:10:32 +02:00
{
2018-07-31 23:09:47 +02:00
u8 holdEffect = GetBattlerHoldEffect ( battlerId , TRUE ) ;
2018-02-08 11:17:41 +01:00
u16 * choicedMove = & gBattleStruct - > choicedMove [ battlerId ] ;
2017-09-17 14:10:32 +02:00
s32 i ;
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = battlerId ;
2017-09-17 14:10:32 +02:00
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-09-17 14:10:32 +02:00
{
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . moves [ i ] = = 0 & & check & MOVE_LIMITATION_ZEROMOVE )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-07-31 23:09:47 +02:00
else if ( gBattleMons [ battlerId ] . pp [ i ] = = 0 & & check & MOVE_LIMITATION_PP )
unusableMoves | = gBitTable [ i ] ;
else if ( gBattleMons [ battlerId ] . moves [ i ] = = gDisableStructs [ battlerId ] . disabledMove & & check & MOVE_LIMITATION_DISABLED )
unusableMoves | = gBitTable [ i ] ;
else if ( gBattleMons [ battlerId ] . moves [ i ] = = gLastMoves [ battlerId ] & & check & MOVE_LIMITATION_TORMENTED & & gBattleMons [ battlerId ] . status2 & STATUS2_TORMENT )
unusableMoves | = gBitTable [ i ] ;
2018-10-14 20:51:34 +02:00
else if ( gDisableStructs [ battlerId ] . tauntTimer & & check & MOVE_LIMITATION_TAUNT & & gBattleMoves [ gBattleMons [ battlerId ] . moves [ i ] ] . power = = 0 )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2019-03-05 21:46:45 +01:00
else if ( GetImprisonedMovesCount ( battlerId , gBattleMons [ battlerId ] . moves [ i ] ) & & check & MOVE_LIMITATION_IMPRISON )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-10-14 20:51:34 +02:00
else if ( gDisableStructs [ battlerId ] . encoreTimer & & gDisableStructs [ battlerId ] . encoredMove ! = gBattleMons [ battlerId ] . moves [ i ] )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-07-31 23:09:47 +02:00
else if ( HOLD_EFFECT_CHOICE ( holdEffect ) & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = gBattleMons [ battlerId ] . moves [ i ] )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2021-11-13 14:58:18 +01:00
else if ( holdEffect = = HOLD_EFFECT_ASSAULT_VEST & & gBattleMoves [ gBattleMons [ battlerId ] . moves [ i ] ] . power = = 0 & & gBattleMons [ battlerId ] . moves [ i ] ! = MOVE_ME_FIRST )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-07-31 23:09:47 +02:00
else if ( IsGravityPreventingMove ( gBattleMons [ battlerId ] . moves [ i ] ) )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-07-31 23:09:47 +02:00
else if ( IsHealBlockPreventingMove ( battlerId , gBattleMons [ battlerId ] . moves [ i ] ) )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2019-02-01 14:17:24 +01:00
else if ( IsBelchPreventingMove ( battlerId , gBattleMons [ battlerId ] . moves [ i ] ) )
unusableMoves | = gBitTable [ i ] ;
2019-04-16 15:01:48 +02:00
else if ( gDisableStructs [ battlerId ] . throatChopTimer & & gBattleMoves [ gBattleMons [ battlerId ] . moves [ i ] ] . flags & FLAG_SOUND )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2021-07-27 18:31:48 +02:00
else if ( gBattleMons [ battlerId ] . moves [ i ] = = MOVE_STUFF_CHEEKS & & ItemId_GetPocket ( gBattleMons [ gActiveBattler ] . item ) ! = POCKET_BERRIES )
unusableMoves | = gBitTable [ i ] ;
2021-10-30 07:31:44 +02:00
else if ( GetBattlerAbility ( battlerId ) = = ABILITY_GORILLA_TACTICS & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = gBattleMons [ battlerId ] . moves [ i ] )
unusableMoves | = gBitTable [ i ] ;
2017-09-17 14:10:32 +02:00
}
return unusableMoves ;
}
bool8 AreAllMovesUnusable ( void )
{
u8 unusable ;
2018-02-06 02:46:59 +01:00
unusable = CheckMoveLimitations ( gActiveBattler , 0 , 0xFF ) ;
2017-09-17 14:10:32 +02:00
2018-07-01 11:15:42 +02:00
if ( unusable = = 0xF ) // All moves are unusable.
2017-09-17 14:10:32 +02:00
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . noValidMoves = TRUE ;
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_NoMovesLeft ;
2017-09-17 14:10:32 +02:00
}
else
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gActiveBattler ] . noValidMoves = FALSE ;
2017-09-17 14:10:32 +02:00
}
return ( unusable = = 0xF ) ;
}
2018-02-08 11:17:41 +01:00
u8 GetImprisonedMovesCount ( u8 battlerId , u16 move )
2017-09-17 14:10:32 +02:00
{
s32 i ;
2019-03-02 23:40:38 +01:00
u8 imprisonedMoves = 0 ;
2018-07-16 20:47:30 +02:00
u8 battlerSide = GetBattlerSide ( battlerId ) ;
2017-09-17 14:10:32 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-09-17 14:10:32 +02:00
{
2018-07-16 20:47:30 +02:00
if ( battlerSide ! = GetBattlerSide ( i ) & & gStatuses3 [ i ] & STATUS3_IMPRISONED_OTHERS )
2017-09-17 14:10:32 +02:00
{
s32 j ;
2018-12-25 18:50:15 +01:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
2017-09-17 14:10:32 +02:00
{
if ( move = = gBattleMons [ i ] . moves [ j ] )
break ;
}
2018-12-25 18:50:15 +01:00
if ( j < MAX_MON_MOVES )
2019-03-02 23:40:38 +01:00
imprisonedMoves + + ;
2017-09-17 14:10:32 +02:00
}
}
2019-03-02 23:40:38 +01:00
return imprisonedMoves ;
2017-09-17 14:10:32 +02:00
}
2021-10-31 01:40:05 +02:00
void RestoreBattlerOriginalTypes ( u8 battlerId )
{
gBattleMons [ battlerId ] . type1 = gBaseStats [ gBattleMons [ battlerId ] . species ] . type1 ;
gBattleMons [ battlerId ] . type2 = gBaseStats [ gBattleMons [ battlerId ] . species ] . type2 ;
}
void TryToApplyMimicry ( u8 battlerId , bool8 various )
{
u32 moveType , move ;
GET_MOVE_TYPE ( move , moveType ) ;
switch ( gFieldStatuses )
{
case STATUS_FIELD_ELECTRIC_TERRAIN :
moveType = TYPE_ELECTRIC ;
break ;
case STATUS_FIELD_MISTY_TERRAIN :
moveType = TYPE_FAIRY ;
break ;
case STATUS_FIELD_GRASSY_TERRAIN :
moveType = TYPE_GRASS ;
break ;
case STATUS_FIELD_PSYCHIC_TERRAIN :
moveType = TYPE_PSYCHIC ;
break ;
default :
moveType = 0 ;
break ;
}
if ( moveType ! = 0 & & ! IS_BATTLER_OF_TYPE ( battlerId , moveType ) )
{
SET_BATTLER_TYPE ( battlerId , moveType ) ;
PREPARE_MON_NICK_WITH_PREFIX_BUFFER ( gBattleTextBuff1 , battlerId , gBattlerPartyIndexes [ battlerId ] )
PREPARE_TYPE_BUFFER ( gBattleTextBuff2 , moveType ) ;
if ( ! various )
BattleScriptPushCursorAndCallback ( BattleScript_MimicryActivatesEnd3 ) ;
}
}
2021-11-04 16:20:31 +01:00
void TryToRevertMimicry ( void )
{
s32 i ;
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
{
if ( GetBattlerAbility ( i ) = = ABILITY_MIMICRY )
RestoreBattlerOriginalTypes ( i ) ;
}
}
2018-08-03 00:13:44 +02:00
enum
{
2020-10-19 23:01:19 +02:00
ENDTURN_ORDER ,
ENDTURN_REFLECT ,
ENDTURN_LIGHT_SCREEN ,
ENDTURN_AURORA_VEIL ,
ENDTURN_MIST ,
ENDTURN_LUCKY_CHANT ,
ENDTURN_SAFEGUARD ,
ENDTURN_TAILWIND ,
ENDTURN_WISH ,
ENDTURN_RAIN ,
ENDTURN_SANDSTORM ,
ENDTURN_SUN ,
ENDTURN_HAIL ,
ENDTURN_GRAVITY ,
ENDTURN_WATER_SPORT ,
ENDTURN_MUD_SPORT ,
ENDTURN_TRICK_ROOM ,
ENDTURN_WONDER_ROOM ,
ENDTURN_MAGIC_ROOM ,
ENDTURN_ELECTRIC_TERRAIN ,
ENDTURN_MISTY_TERRAIN ,
ENDTURN_GRASSY_TERRAIN ,
ENDTURN_PSYCHIC_TERRAIN ,
ENDTURN_ION_DELUGE ,
ENDTURN_FAIRY_LOCK ,
2021-10-16 10:41:50 +02:00
ENDTURN_RETALIATE ,
2020-10-19 23:01:19 +02:00
ENDTURN_FIELD_COUNT ,
2018-08-03 00:13:44 +02:00
} ;
u8 DoFieldEndTurnEffects ( void )
2017-09-17 14:10:32 +02:00
{
u8 effect = 0 ;
2018-02-06 23:09:39 +01:00
for ( gBattlerAttacker = 0 ; gBattlerAttacker < gBattlersCount & & gAbsentBattlerFlags & gBitTable [ gBattlerAttacker ] ; gBattlerAttacker + + )
2017-09-17 14:10:32 +02:00
{
}
2018-02-06 23:09:39 +01:00
for ( gBattlerTarget = 0 ; gBattlerTarget < gBattlersCount & & gAbsentBattlerFlags & gBitTable [ gBattlerTarget ] ; gBattlerTarget + + )
2017-09-17 14:10:32 +02:00
{
}
do
{
2018-07-21 13:24:20 +02:00
s32 i ;
2018-07-01 11:15:42 +02:00
u8 side ;
2017-09-17 14:10:32 +02:00
2018-02-07 22:53:40 +01:00
switch ( gBattleStruct - > turnCountersTracker )
2017-09-17 14:10:32 +02:00
{
2018-08-03 00:13:44 +02:00
case ENDTURN_ORDER :
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-09-17 14:10:32 +02:00
{
2018-06-28 21:06:32 +02:00
gBattlerByTurnOrder [ i ] = i ;
2017-09-17 14:10:32 +02:00
}
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount - 1 ; i + + )
2017-09-17 14:10:32 +02:00
{
s32 j ;
2018-02-06 02:46:59 +01:00
for ( j = i + 1 ; j < gBattlersCount ; j + + )
2017-09-17 14:10:32 +02:00
{
2018-06-28 21:06:32 +02:00
if ( GetWhoStrikesFirst ( gBattlerByTurnOrder [ i ] , gBattlerByTurnOrder [ j ] , 0 ) )
2017-10-04 19:25:14 +02:00
SwapTurnOrder ( i , j ) ;
2017-09-17 14:10:32 +02:00
}
}
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnCountersTracker + + ;
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker = 0 ;
2017-09-17 14:10:32 +02:00
// fall through
2018-08-03 00:13:44 +02:00
case ENDTURN_REFLECT :
2017-09-17 14:10:32 +02:00
while ( gBattleStruct - > turnSideTracker < 2 )
{
2018-07-01 11:15:42 +02:00
side = gBattleStruct - > turnSideTracker ;
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . reflectBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_REFLECT )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
if ( - - gSideTimers [ side ] . reflectTimer = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
gSideStatuses [ side ] & = ~ SIDE_STATUS_REFLECT ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_REFLECT ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_LIGHT_SCREEN :
2017-09-17 14:10:32 +02:00
while ( gBattleStruct - > turnSideTracker < 2 )
{
2018-07-01 11:15:42 +02:00
side = gBattleStruct - > turnSideTracker ;
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . lightscreenBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_LIGHTSCREEN )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
if ( - - gSideTimers [ side ] . lightscreenTimer = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
gSideStatuses [ side ] & = ~ SIDE_STATUS_LIGHTSCREEN ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
2018-07-01 11:15:42 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = side ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_LIGHT_SCREEN ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
2018-07-21 12:56:07 +02:00
case ENDTURN_AURORA_VEIL :
2018-12-09 13:12:02 +01:00
while ( gBattleStruct - > turnSideTracker < 2 )
2018-07-21 12:56:07 +02:00
{
2018-12-09 13:12:02 +01:00
side = gBattleStruct - > turnSideTracker ;
2018-07-21 12:56:07 +02:00
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . auroraVeilBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_AURORA_VEIL )
{
if ( - - gSideTimers [ side ] . auroraVeilTimer = = 0 )
{
gSideStatuses [ side ] & = ~ SIDE_STATUS_AURORA_VEIL ;
2018-09-23 19:03:53 +02:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = side ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_AURORA_VEIL ) ;
2018-07-21 12:56:07 +02:00
effect + + ;
}
}
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker + + ;
2018-07-21 12:56:07 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turnCountersTracker + + ;
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker = 0 ;
2018-07-21 12:56:07 +02:00
}
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_MIST :
2017-09-17 14:10:32 +02:00
while ( gBattleStruct - > turnSideTracker < 2 )
{
2018-07-01 11:15:42 +02:00
side = gBattleStruct - > turnSideTracker ;
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . mistBattlerId ;
if ( gSideTimers [ side ] . mistTimer ! = 0
& & - - gSideTimers [ side ] . mistTimer = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
gSideStatuses [ side ] & = ~ SIDE_STATUS_MIST ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
2018-07-01 11:15:42 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = side ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_MIST ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_SAFEGUARD :
2017-09-17 14:10:32 +02:00
while ( gBattleStruct - > turnSideTracker < 2 )
{
2018-07-01 11:15:42 +02:00
side = gBattleStruct - > turnSideTracker ;
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . safeguardBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_SAFEGUARD )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
if ( - - gSideTimers [ side ] . safeguardTimer = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
gSideStatuses [ side ] & = ~ SIDE_STATUS_SAFEGUARD ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SafeguardEnds ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
2018-07-21 12:56:07 +02:00
case ENDTURN_LUCKY_CHANT :
2018-12-09 13:12:02 +01:00
while ( gBattleStruct - > turnSideTracker < 2 )
2018-07-21 12:56:07 +02:00
{
2018-12-09 13:12:02 +01:00
side = gBattleStruct - > turnSideTracker ;
2018-07-21 12:56:07 +02:00
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . luckyChantBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_LUCKY_CHANT )
{
if ( - - gSideTimers [ side ] . luckyChantTimer = = 0 )
{
gSideStatuses [ side ] & = ~ SIDE_STATUS_LUCKY_CHANT ;
BattleScriptExecute ( BattleScript_LuckyChantEnds ) ;
effect + + ;
}
}
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker + + ;
2018-07-21 12:56:07 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turnCountersTracker + + ;
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker = 0 ;
2018-07-21 12:56:07 +02:00
}
break ;
case ENDTURN_TAILWIND :
2018-12-09 13:12:02 +01:00
while ( gBattleStruct - > turnSideTracker < 2 )
2018-07-21 12:56:07 +02:00
{
2018-12-09 13:12:02 +01:00
side = gBattleStruct - > turnSideTracker ;
2018-07-21 12:56:07 +02:00
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . tailwindBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_TAILWIND )
{
if ( - - gSideTimers [ side ] . tailwindTimer = = 0 )
{
gSideStatuses [ side ] & = ~ SIDE_STATUS_TAILWIND ;
BattleScriptExecute ( BattleScript_TailwindEnds ) ;
effect + + ;
}
}
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker + + ;
2018-07-21 12:56:07 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turnCountersTracker + + ;
2018-12-09 13:12:02 +01:00
gBattleStruct - > turnSideTracker = 0 ;
2018-07-21 12:56:07 +02:00
}
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_WISH :
2018-02-06 02:46:59 +01:00
while ( gBattleStruct - > turnSideTracker < gBattlersCount )
2017-09-17 14:10:32 +02:00
{
2018-06-28 21:06:32 +02:00
gActiveBattler = gBattlerByTurnOrder [ gBattleStruct - > turnSideTracker ] ;
2018-02-06 02:46:59 +01:00
if ( gWishFutureKnock . wishCounter [ gActiveBattler ] ! = 0
& & - - gWishFutureKnock . wishCounter [ gActiveBattler ] = = 0
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattlerTarget = gActiveBattler ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_WishComesTrue ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
}
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_RAIN :
2017-09-17 14:10:32 +02:00
if ( gBattleWeather & WEATHER_RAIN_ANY )
{
2021-08-26 21:14:05 +02:00
if ( ! ( gBattleWeather & WEATHER_RAIN_PERMANENT )
& & ! ( gBattleWeather & WEATHER_RAIN_PRIMAL ) )
2017-09-17 14:10:32 +02:00
{
if ( - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_RAIN_TEMPORARY ;
gBattleWeather & = ~ WEATHER_RAIN_DOWNPOUR ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_RAIN_STOPPED ;
2017-09-17 14:10:32 +02:00
}
else if ( gBattleWeather & WEATHER_RAIN_DOWNPOUR )
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_DOWNPOUR_CONTINUES ;
2017-09-17 14:10:32 +02:00
else
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_RAIN_CONTINUES ;
2017-09-17 14:10:32 +02:00
}
else if ( gBattleWeather & WEATHER_RAIN_DOWNPOUR )
2017-11-26 17:15:28 +01:00
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_DOWNPOUR_CONTINUES ;
2017-11-26 17:15:28 +01:00
}
2017-09-17 14:10:32 +02:00
else
2017-11-26 17:15:28 +01:00
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_RAIN_CONTINUES ;
2017-11-26 17:15:28 +01:00
}
BattleScriptExecute ( BattleScript_RainContinuesOrEnds ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_SANDSTORM :
2017-09-17 14:10:32 +02:00
if ( gBattleWeather & WEATHER_SANDSTORM_ANY )
{
if ( ! ( gBattleWeather & WEATHER_SANDSTORM_PERMANENT ) & & - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_SANDSTORM_TEMPORARY ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_SandStormHailEnds ;
2017-09-17 14:10:32 +02:00
}
else
2017-11-26 17:15:28 +01:00
{
gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues ;
}
2017-09-17 14:10:32 +02:00
2017-11-26 17:15:28 +01:00
gBattleScripting . animArg1 = B_ANIM_SANDSTORM_CONTINUES ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SANDSTORM ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_SUN :
2017-09-17 14:10:32 +02:00
if ( gBattleWeather & WEATHER_SUN_ANY )
{
2021-08-26 21:14:05 +02:00
if ( ! ( gBattleWeather & WEATHER_SUN_PERMANENT )
& & ! ( gBattleWeather & WEATHER_SUN_PRIMAL )
& & - - gWishFutureKnock . weatherDuration = = 0 )
2017-09-17 14:10:32 +02:00
{
gBattleWeather & = ~ WEATHER_SUN_TEMPORARY ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_SunlightFaded ;
2017-09-17 14:10:32 +02:00
}
else
2017-11-26 17:15:28 +01:00
{
gBattlescriptCurrInstr = BattleScript_SunlightContinues ;
}
2017-09-17 14:10:32 +02:00
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
break ;
2018-08-03 00:13:44 +02:00
case ENDTURN_HAIL :
if ( gBattleWeather & WEATHER_HAIL_ANY )
2017-09-17 14:10:32 +02:00
{
2018-07-27 23:40:10 +02:00
if ( ! ( gBattleWeather & WEATHER_HAIL_PERMANENT ) & & - - gWishFutureKnock . weatherDuration = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-27 23:40:10 +02:00
gBattleWeather & = ~ WEATHER_HAIL_TEMPORARY ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_SandStormHailEnds ;
2017-09-17 14:10:32 +02:00
}
else
2017-11-26 13:26:58 +01:00
{
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues ;
2017-11-26 13:26:58 +01:00
}
2017-09-17 14:10:32 +02:00
2017-11-26 13:26:58 +01:00
gBattleScripting . animArg1 = B_ANIM_HAIL_CONTINUES ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_HAIL ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
break ;
2018-07-21 13:24:20 +02:00
case ENDTURN_TRICK_ROOM :
if ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM & & - - gFieldTimers . trickRoomTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_TRICK_ROOM ) ;
BattleScriptExecute ( BattleScript_TrickRoomEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
2017-09-17 14:10:32 +02:00
break ;
2018-07-21 13:24:20 +02:00
case ENDTURN_WONDER_ROOM :
if ( gFieldStatuses & STATUS_FIELD_WONDER_ROOM & & - - gFieldTimers . wonderRoomTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_WONDER_ROOM ) ;
BattleScriptExecute ( BattleScript_WonderRoomEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_MAGIC_ROOM :
if ( gFieldStatuses & STATUS_FIELD_MAGIC_ROOM & & - - gFieldTimers . magicRoomTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_MAGIC_ROOM ) ;
BattleScriptExecute ( BattleScript_MagicRoomEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_ELECTRIC_TERRAIN :
2020-12-14 03:42:48 +01:00
if ( gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN
2021-11-06 23:46:52 +01:00
& & ( ! ( gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT ) & & - - gFieldTimers . terrainTimer = = 0 ) )
2018-07-21 13:24:20 +02:00
{
2020-12-14 03:42:48 +01:00
gFieldStatuses & = ~ ( STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT ) ;
2021-11-04 16:20:31 +01:00
TryToRevertMimicry ( ) ;
2018-07-21 13:24:20 +02:00
BattleScriptExecute ( BattleScript_ElectricTerrainEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_MISTY_TERRAIN :
2020-12-14 03:42:48 +01:00
if ( gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN
2021-11-06 23:46:52 +01:00
& & ( ! ( gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT ) & & - - gFieldTimers . terrainTimer = = 0 ) )
2018-07-21 13:24:20 +02:00
{
gFieldStatuses & = ~ ( STATUS_FIELD_MISTY_TERRAIN ) ;
2021-11-04 16:20:31 +01:00
TryToRevertMimicry ( ) ;
2018-07-21 13:24:20 +02:00
BattleScriptExecute ( BattleScript_MistyTerrainEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_GRASSY_TERRAIN :
2019-02-28 15:02:54 +01:00
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN )
{
2020-12-14 03:42:48 +01:00
if ( ! ( gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT )
2021-11-06 23:46:52 +01:00
& & ( gFieldTimers . terrainTimer = = 0 | | - - gFieldTimers . terrainTimer = = 0 ) )
2021-10-31 01:40:05 +02:00
{
2019-03-02 23:54:08 +01:00
gFieldStatuses & = ~ ( STATUS_FIELD_GRASSY_TERRAIN ) ;
2021-11-04 16:20:31 +01:00
TryToRevertMimicry ( ) ;
2021-10-31 01:40:05 +02:00
}
2020-06-29 18:26:53 +02:00
BattleScriptExecute ( BattleScript_GrassyTerrainHeals ) ;
2019-02-28 15:02:54 +01:00
effect + + ;
}
2018-07-21 13:24:20 +02:00
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_PSYCHIC_TERRAIN :
2020-12-14 03:42:48 +01:00
if ( gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN
2021-11-06 23:46:52 +01:00
& & ( ! ( gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT ) & & - - gFieldTimers . terrainTimer = = 0 ) )
2018-07-21 13:24:20 +02:00
{
gFieldStatuses & = ~ ( STATUS_FIELD_PSYCHIC_TERRAIN ) ;
2021-11-04 16:20:31 +01:00
TryToRevertMimicry ( ) ;
2018-07-21 13:24:20 +02:00
BattleScriptExecute ( BattleScript_PsychicTerrainEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_WATER_SPORT :
if ( gFieldStatuses & STATUS_FIELD_WATERSPORT & & - - gFieldTimers . waterSportTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_WATERSPORT ) ;
BattleScriptExecute ( BattleScript_WaterSportEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_MUD_SPORT :
if ( gFieldStatuses & STATUS_FIELD_MUDSPORT & & - - gFieldTimers . mudSportTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_MUDSPORT ) ;
BattleScriptExecute ( BattleScript_MudSportEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
2018-07-21 16:34:43 +02:00
case ENDTURN_GRAVITY :
if ( gFieldStatuses & STATUS_FIELD_GRAVITY & & - - gFieldTimers . gravityTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_GRAVITY ) ;
BattleScriptExecute ( BattleScript_GravityEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
2018-08-04 23:34:29 +02:00
case ENDTURN_ION_DELUGE :
gFieldStatuses & = ~ ( STATUS_FIELD_ION_DELUGE ) ;
gBattleStruct - > turnCountersTracker + + ;
break ;
2020-04-20 19:41:07 +02:00
case ENDTURN_FAIRY_LOCK :
if ( gFieldStatuses & STATUS_FIELD_FAIRY_LOCK & & - - gFieldTimers . fairyLockTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_FAIRY_LOCK ) ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
2021-10-16 10:41:50 +02:00
case ENDTURN_RETALIATE :
2021-10-22 16:43:38 +02:00
if ( gSideTimers [ B_SIDE_PLAYER ] . retaliateTimer > 0 )
gSideTimers [ B_SIDE_PLAYER ] . retaliateTimer - - ;
if ( gSideTimers [ B_SIDE_OPPONENT ] . retaliateTimer > 0 )
gSideTimers [ B_SIDE_OPPONENT ] . retaliateTimer - - ;
2021-10-16 10:41:50 +02:00
gBattleStruct - > turnCountersTracker + + ;
break ;
2018-07-21 12:10:08 +02:00
case ENDTURN_FIELD_COUNT :
2017-09-17 14:10:32 +02:00
effect + + ;
break ;
}
} while ( effect = = 0 ) ;
2018-07-21 13:24:20 +02:00
2017-09-17 14:10:32 +02:00
return ( gBattleMainFunc ! = BattleTurnPassed ) ;
}
2018-07-18 22:07:48 +02:00
enum
{
ENDTURN_INGRAIN ,
ENDTURN_AQUA_RING ,
ENDTURN_ABILITIES ,
2020-10-19 23:01:19 +02:00
ENDTURN_ITEMS1 ,
ENDTURN_LEECH_SEED ,
ENDTURN_POISON ,
ENDTURN_BAD_POISON ,
ENDTURN_BURN ,
ENDTURN_NIGHTMARES ,
ENDTURN_CURSE ,
ENDTURN_WRAP ,
2021-11-04 07:50:54 +01:00
ENDTURN_OCTOLOCK ,
2020-10-19 23:01:19 +02:00
ENDTURN_UPROAR ,
ENDTURN_THRASH ,
ENDTURN_FLINCH ,
ENDTURN_DISABLE ,
ENDTURN_ENCORE ,
ENDTURN_MAGNET_RISE ,
ENDTURN_TELEKINESIS ,
ENDTURN_HEALBLOCK ,
ENDTURN_EMBARGO ,
ENDTURN_LOCK_ON ,
ENDTURN_CHARGE ,
ENDTURN_LASER_FOCUS ,
ENDTURN_TAUNT ,
ENDTURN_YAWN ,
ENDTURN_ITEMS2 ,
ENDTURN_ORBS ,
ENDTURN_ROOST ,
ENDTURN_ELECTRIFY ,
ENDTURN_POWDER ,
ENDTURN_THROAT_CHOP ,
ENDTURN_SLOW_START ,
2021-10-17 17:27:17 +02:00
ENDTURN_PLASMA_FISTS ,
2020-10-19 23:01:19 +02:00
ENDTURN_BATTLER_COUNT
2018-07-18 22:07:48 +02:00
} ;
2017-09-17 14:10:32 +02:00
2020-04-13 15:00:17 +02:00
// Ingrain, Leech Seed, Strength Sap and Aqua Ring
s32 GetDrainedBigRootHp ( u32 battler , s32 hp )
{
if ( GetBattlerHoldEffect ( battler , TRUE ) = = HOLD_EFFECT_BIG_ROOT )
hp = ( hp * 1300 ) / 1000 ;
if ( hp = = 0 )
hp = 1 ;
return hp * - 1 ;
}
2021-05-01 12:37:23 +02:00
# define MAGIC_GUARD_CHECK \
2020-06-26 15:14:15 +02:00
if ( ability = = ABILITY_MAGIC_GUARD ) \
{ \
RecordAbilityBattle ( gActiveBattler , ability ) ; \
gBattleStruct - > turnEffectsTracker + + ; \
break ; \
}
2018-07-18 22:07:48 +02:00
u8 DoBattlerEndTurnEffects ( void )
2017-09-17 14:10:32 +02:00
{
2020-06-26 15:14:15 +02:00
u32 ability , i , effect = 0 ;
2017-09-17 14:10:32 +02:00
2021-10-29 15:03:14 +02:00
gHitMarker | = ( HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK ) ;
2018-07-18 22:07:48 +02:00
while ( gBattleStruct - > turnEffectsBattlerId < gBattlersCount & & gBattleStruct - > turnEffectsTracker < = ENDTURN_BATTLER_COUNT )
2017-09-17 14:10:32 +02:00
{
2018-06-28 21:06:32 +02:00
gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder [ gBattleStruct - > turnEffectsBattlerId ] ;
2018-02-06 02:46:59 +01:00
if ( gAbsentBattlerFlags & gBitTable [ gActiveBattler ] )
2017-09-17 14:10:32 +02:00
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnEffectsBattlerId + + ;
2019-08-22 15:57:33 +02:00
continue ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
ability = GetBattlerAbility ( gActiveBattler ) ;
switch ( gBattleStruct - > turnEffectsTracker )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
case ENDTURN_INGRAIN : // ingrain
if ( ( gStatuses3 [ gActiveBattler ] & STATUS3_ROOTED )
& & ! BATTLER_MAX_HP ( gActiveBattler )
& & ! ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK )
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2017-09-17 14:10:32 +02:00
{
2020-04-13 15:00:17 +02:00
gBattleMoveDamage = GetDrainedBigRootHp ( gActiveBattler , gBattleMons [ gActiveBattler ] . maxHP / 16 ) ;
2019-08-22 15:57:33 +02:00
BattleScriptExecute ( BattleScript_IngrainTurnHeal ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_AQUA_RING : // aqua ring
if ( ( gStatuses3 [ gActiveBattler ] & STATUS3_AQUA_RING )
& & ! BATTLER_MAX_HP ( gActiveBattler )
& & ! ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK )
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
{
2020-04-13 15:00:17 +02:00
gBattleMoveDamage = GetDrainedBigRootHp ( gActiveBattler , gBattleMons [ gActiveBattler ] . maxHP / 16 ) ;
2019-08-22 15:57:33 +02:00
BattleScriptExecute ( BattleScript_AquaRingHeal ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ABILITIES : // end turn abilities
if ( AbilityBattleEffects ( ABILITYEFFECT_ENDTURN , gActiveBattler , 0 , 0 , 0 ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ITEMS1 : // item effects
if ( ItemBattleEffects ( 1 , gActiveBattler , FALSE ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ITEMS2 : // item effects again
if ( ItemBattleEffects ( 1 , gActiveBattler , TRUE ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ORBS :
if ( ItemBattleEffects ( ITEMEFFECT_ORBS , gActiveBattler , FALSE ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_LEECH_SEED : // leech seed
if ( ( gStatuses3 [ gActiveBattler ] & STATUS3_LEECHSEED )
& & gBattleMons [ gStatuses3 [ gActiveBattler ] & STATUS3_LEECHSEED_BATTLER ] . hp ! = 0
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2020-06-26 15:14:15 +02:00
2019-08-22 15:57:33 +02:00
gBattlerTarget = gStatuses3 [ gActiveBattler ] & STATUS3_LEECHSEED_BATTLER ; // Notice gBattlerTarget is actually the HP receiver.
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleScripting . animArg1 = gBattlerTarget ;
gBattleScripting . animArg2 = gBattlerAttacker ;
BattleScriptExecute ( BattleScript_LeechSeedTurnDrain ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_POISON : // poison
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_POISON )
2020-06-26 15:14:15 +02:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2019-08-22 15:57:33 +02:00
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2020-06-26 15:14:15 +02:00
2019-08-22 15:57:33 +02:00
if ( ability = = ABILITY_POISON_HEAL )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
if ( ! BATTLER_MAX_HP ( gActiveBattler ) & & ! ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK ) )
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
BattleScriptExecute ( BattleScript_PoisonHealActivates ) ;
effect + + ;
}
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
else
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
2017-09-17 14:10:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2019-08-22 15:57:33 +02:00
BattleScriptExecute ( BattleScript_PoisonTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_BAD_POISON : // toxic poison
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_TOXIC_POISON )
2020-06-26 15:14:15 +02:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2019-08-22 15:57:33 +02:00
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2020-06-26 15:14:15 +02:00
2019-08-22 15:57:33 +02:00
if ( ability = = ABILITY_POISON_HEAL )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
if ( ! BATTLER_MAX_HP ( gActiveBattler ) & & ! ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK ) )
2018-07-22 18:40:18 +02:00
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2019-08-22 15:57:33 +02:00
gBattleMoveDamage * = - 1 ;
BattleScriptExecute ( BattleScript_PoisonHealActivates ) ;
2018-07-22 18:40:18 +02:00
effect + + ;
}
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
else
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 16 ;
2017-09-17 14:10:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2020-07-17 02:12:12 +02:00
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_TOXIC_COUNTER ) ! = STATUS1_TOXIC_TURN ( 15 ) ) // not 16 turns
gBattleMons [ gActiveBattler ] . status1 + = STATUS1_TOXIC_TURN ( 1 ) ;
gBattleMoveDamage * = ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_TOXIC_COUNTER ) > > 8 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_PoisonTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_BURN : // burn
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_BURN )
2020-06-26 15:14:15 +02:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2019-08-22 15:57:33 +02:00
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2020-06-26 15:14:15 +02:00
2020-02-08 09:51:55 +01:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / ( B_BURN_DAMAGE > = GEN_7 ? 16 : 8 ) ;
2019-12-23 17:41:42 +01:00
if ( ability = = ABILITY_HEATPROOF )
2017-09-17 14:10:32 +02:00
{
2020-07-12 10:09:23 +02:00
if ( gBattleMoveDamage > ( gBattleMoveDamage / 2 ) + 1 ) // Record ability if the burn takes less damage than it normally would.
RecordAbilityBattle ( gActiveBattler , ABILITY_HEATPROOF ) ;
2019-12-23 17:41:42 +01:00
gBattleMoveDamage / = 2 ;
2020-07-12 10:09:23 +02:00
}
2019-08-22 15:57:33 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptExecute ( BattleScript_BurnTurnDmg ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_NIGHTMARES : // spooky nightmares
if ( ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_NIGHTMARE )
2020-06-26 15:14:15 +02:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2019-08-22 15:57:33 +02:00
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2019-08-22 15:57:33 +02:00
// R/S does not perform this sleep check, which causes the nightmare effect to
// persist even after the affected Pokemon has been awakened by Shed Skin.
if ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_SLEEP )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 4 ;
2017-09-17 14:10:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2019-08-22 15:57:33 +02:00
BattleScriptExecute ( BattleScript_NightmareTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
2019-08-22 15:57:33 +02:00
else
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
gBattleMons [ gActiveBattler ] . status2 & = ~ STATUS2_NIGHTMARE ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_CURSE : // curse
if ( ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_CURSED )
2020-06-26 15:14:15 +02:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2019-08-22 15:57:33 +02:00
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2019-08-22 15:57:33 +02:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptExecute ( BattleScript_CurseTurnDmg ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_WRAP : // wrap
if ( ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_WRAPPED ) & & gBattleMons [ gActiveBattler ] . hp ! = 0 )
{
if ( - - gDisableStructs [ gActiveBattler ] . wrapTurns ! = 0 ) // damaged by wrap
2017-09-17 14:10:32 +02:00
{
2021-05-01 12:37:23 +02:00
MAGIC_GUARD_CHECK ;
2020-06-26 15:14:15 +02:00
2019-08-22 15:57:33 +02:00
gBattleScripting . animArg1 = gBattleStruct - > wrappedMove [ gActiveBattler ] ;
gBattleScripting . animArg2 = gBattleStruct - > wrappedMove [ gActiveBattler ] > > 8 ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , gBattleStruct - > wrappedMove [ gActiveBattler ] ) ;
gBattlescriptCurrInstr = BattleScript_WrapTurnDmg ;
if ( GetBattlerHoldEffect ( gBattleStruct - > wrappedBy [ gActiveBattler ] , TRUE ) = = HOLD_EFFECT_BINDING_BAND )
2021-01-15 16:04:09 +01:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / ( ( B_BINDING_DAMAGE > = GEN_6 ) ? 6 : 8 ) ;
2019-08-22 15:57:33 +02:00
else
2021-01-15 16:04:09 +01:00
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / ( ( B_BINDING_DAMAGE > = GEN_6 ) ? 8 : 16 ) ;
2018-09-22 12:20:33 +02:00
2017-09-17 14:10:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
}
2019-08-22 15:57:33 +02:00
else // broke free
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_WRAPPED ) ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , gBattleStruct - > wrappedMove [ gActiveBattler ] ) ;
gBattlescriptCurrInstr = BattleScript_WrapEnds ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2021-11-04 07:50:54 +01:00
case ENDTURN_OCTOLOCK :
if ( gDisableStructs [ gActiveBattler ] . octolock
& & ! ( GetBattlerAbility ( gActiveBattler ) = = ABILITY_CLEAR_BODY
| | GetBattlerAbility ( gActiveBattler ) = = ABILITY_FULL_METAL_BODY
| | GetBattlerAbility ( gActiveBattler ) = = ABILITY_WHITE_SMOKE ) )
{
gBattlerTarget = gActiveBattler ;
BattleScriptExecute ( BattleScript_OctolockEndTurn ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2019-08-22 15:57:33 +02:00
case ENDTURN_UPROAR : // uproar
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_UPROAR )
{
for ( gBattlerAttacker = 0 ; gBattlerAttacker < gBattlersCount ; gBattlerAttacker + + )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
if ( ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_SLEEP )
2021-10-31 22:19:30 +01:00
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_SOUNDPROOF )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
gBattleMons [ gBattlerAttacker ] . status1 & = ~ ( STATUS1_SLEEP ) ;
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
BattleScriptExecute ( BattleScript_MonWokeUpInUproar ) ;
gActiveBattler = gBattlerAttacker ;
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 14:10:32 +02:00
break ;
}
}
2019-08-22 15:57:33 +02:00
if ( gBattlerAttacker ! = gBattlersCount )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
effect = 2 ; // a pokemon was awaken
break ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
else
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
gBattlerAttacker = gActiveBattler ;
2020-07-27 14:51:39 +02:00
gBattleMons [ gActiveBattler ] . status2 - = STATUS2_UPROAR_TURN ( 1 ) ; // uproar timer goes down
2019-08-22 15:57:33 +02:00
if ( WasUnableToUseMove ( gActiveBattler ) )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
CancelMultiTurnMoves ( gActiveBattler ) ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_UPROAR_ENDS ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
else if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_UPROAR )
2017-09-17 14:10:32 +02:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_UPROAR_CONTINUES ;
2019-08-22 15:57:33 +02:00
gBattleMons [ gActiveBattler ] . status2 | = STATUS2_MULTIPLETURNS ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
else
2017-09-17 14:10:32 +02:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_UPROAR_ENDS ;
2019-08-22 15:57:33 +02:00
CancelMultiTurnMoves ( gActiveBattler ) ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
BattleScriptExecute ( BattleScript_PrintUproarOverTurns ) ;
effect = 1 ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
}
if ( effect ! = 2 )
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnEffectsTracker + + ;
2019-08-22 15:57:33 +02:00
break ;
case ENDTURN_THRASH : // thrash
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_LOCK_CONFUSE )
{
2020-07-27 14:51:39 +02:00
gBattleMons [ gActiveBattler ] . status2 - = STATUS2_LOCK_CONFUSE_TURN ( 1 ) ;
2019-08-22 15:57:33 +02:00
if ( WasUnableToUseMove ( gActiveBattler ) )
CancelMultiTurnMoves ( gActiveBattler ) ;
else if ( ! ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_LOCK_CONFUSE )
& & ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_MULTIPLETURNS ) )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_MULTIPLETURNS ) ;
if ( ! ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_CONFUSION ) )
2017-09-17 14:10:32 +02:00
{
2019-08-22 15:57:33 +02:00
gBattleScripting . moveEffect = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER ;
2020-03-13 23:02:17 +01:00
SetMoveEffect ( TRUE , 0 ) ;
2019-08-22 15:57:33 +02:00
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_CONFUSION )
BattleScriptExecute ( BattleScript_ThrashConfuses ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2019-11-14 00:03:20 +01:00
case ENDTURN_FLINCH : // reset flinch
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_FLINCHED ) ;
gBattleStruct - > turnEffectsTracker + + ;
2021-11-21 00:35:56 +01:00
break ;
2019-08-22 15:57:33 +02:00
case ENDTURN_DISABLE : // disable
if ( gDisableStructs [ gActiveBattler ] . disableTimer ! = 0 )
{
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2018-02-06 02:46:59 +01:00
{
2019-08-22 15:57:33 +02:00
if ( gDisableStructs [ gActiveBattler ] . disabledMove = = gBattleMons [ gActiveBattler ] . moves [ i ] )
break ;
2019-03-24 03:45:21 +01:00
}
2019-08-22 15:57:33 +02:00
if ( i = = MAX_MON_MOVES ) // pokemon does not have the disabled move anymore
2018-02-06 02:46:59 +01:00
{
2019-08-22 15:57:33 +02:00
gDisableStructs [ gActiveBattler ] . disabledMove = 0 ;
gDisableStructs [ gActiveBattler ] . disableTimer = 0 ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
else if ( - - gDisableStructs [ gActiveBattler ] . disableTimer = = 0 ) // disable ends
2018-07-23 21:36:05 +02:00
{
2019-08-22 15:57:33 +02:00
gDisableStructs [ gActiveBattler ] . disabledMove = 0 ;
BattleScriptExecute ( BattleScript_DisabledNoMore ) ;
effect + + ;
2017-09-17 14:10:32 +02:00
}
}
2019-08-22 15:57:33 +02:00
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ENCORE : // encore
if ( gDisableStructs [ gActiveBattler ] . encoreTimer ! = 0 )
{
if ( gBattleMons [ gActiveBattler ] . moves [ gDisableStructs [ gActiveBattler ] . encoredMovePos ] ! = gDisableStructs [ gActiveBattler ] . encoredMove ) // pokemon does not have the encored move anymore
2018-07-18 22:07:48 +02:00
{
2019-08-22 15:57:33 +02:00
gDisableStructs [ gActiveBattler ] . encoredMove = 0 ;
gDisableStructs [ gActiveBattler ] . encoreTimer = 0 ;
2018-07-18 22:07:48 +02:00
}
2019-08-22 15:57:33 +02:00
else if ( - - gDisableStructs [ gActiveBattler ] . encoreTimer = = 0
| | gBattleMons [ gActiveBattler ] . pp [ gDisableStructs [ gActiveBattler ] . encoredMovePos ] = = 0 )
2018-07-18 22:07:48 +02:00
{
2019-08-22 15:57:33 +02:00
gDisableStructs [ gActiveBattler ] . encoredMove = 0 ;
gDisableStructs [ gActiveBattler ] . encoreTimer = 0 ;
BattleScriptExecute ( BattleScript_EncoredNoMore ) ;
effect + + ;
2018-07-18 22:07:48 +02:00
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_LOCK_ON : // lock-on decrement
if ( gStatuses3 [ gActiveBattler ] & STATUS3_ALWAYS_HITS )
2020-07-27 14:51:39 +02:00
gStatuses3 [ gActiveBattler ] - = STATUS3_ALWAYS_HITS_TURN ( 1 ) ;
2019-08-22 15:57:33 +02:00
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_CHARGE : // charge
if ( gDisableStructs [ gActiveBattler ] . chargeTimer & & - - gDisableStructs [ gActiveBattler ] . chargeTimer = = 0 )
gStatuses3 [ gActiveBattler ] & = ~ STATUS3_CHARGED_UP ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_TAUNT : // taunt
if ( gDisableStructs [ gActiveBattler ] . tauntTimer & & - - gDisableStructs [ gActiveBattler ] . tauntTimer = = 0 )
{
BattleScriptExecute ( BattleScript_BufferEndTurn ) ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_TAUNT ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_YAWN : // yawn
if ( gStatuses3 [ gActiveBattler ] & STATUS3_YAWN )
{
2020-07-27 14:51:39 +02:00
gStatuses3 [ gActiveBattler ] - = STATUS3_YAWN_TURN ( 1 ) ;
2019-08-22 15:57:33 +02:00
if ( ! ( gStatuses3 [ gActiveBattler ] & STATUS3_YAWN ) & & ! ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_ANY )
2021-10-02 23:44:04 +02:00
& & GetBattlerAbility ( gActiveBattler ) ! = ABILITY_VITAL_SPIRIT
& & GetBattlerAbility ( gActiveBattler ) ! = ABILITY_INSOMNIA & & ! UproarWakeUpCheck ( gActiveBattler )
2019-12-16 09:29:20 +01:00
& & ! IsLeafGuardProtected ( gActiveBattler ) )
2019-08-22 15:57:33 +02:00
{
CancelMultiTurnMoves ( gActiveBattler ) ;
gEffectBattler = gActiveBattler ;
2021-08-12 22:08:41 +02:00
if ( IsBattlerTerrainAffected ( gActiveBattler , STATUS_FIELD_ELECTRIC_TERRAIN ) )
{
2021-09-15 23:15:50 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_TERRAINPREVENTS_ELECTRIC ;
2021-08-12 22:08:41 +02:00
BattleScriptExecute ( BattleScript_TerrainPreventsEnd2 ) ;
}
else if ( IsBattlerTerrainAffected ( gActiveBattler , STATUS_FIELD_MISTY_TERRAIN ) )
{
2021-09-15 23:15:50 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_TERRAINPREVENTS_MISTY ;
2021-08-12 22:08:41 +02:00
BattleScriptExecute ( BattleScript_TerrainPreventsEnd2 ) ;
}
else
{
gBattleMons [ gActiveBattler ] . status1 | = ( Random ( ) & 3 ) + 2 ;
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
BattleScriptExecute ( BattleScript_YawnMakesAsleep ) ;
}
2019-08-22 15:57:33 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_LASER_FOCUS :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_LASER_FOCUS )
{
if ( gDisableStructs [ gActiveBattler ] . laserFocusTimer = = 0 | | - - gDisableStructs [ gActiveBattler ] . laserFocusTimer = = 0 )
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_LASER_FOCUS ) ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_EMBARGO :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_EMBARGO )
{
if ( gDisableStructs [ gActiveBattler ] . embargoTimer = = 0 | | - - gDisableStructs [ gActiveBattler ] . embargoTimer = = 0 )
2018-07-18 22:07:48 +02:00
{
2019-08-22 15:57:33 +02:00
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_EMBARGO ) ;
BattleScriptExecute ( BattleScript_EmbargoEndTurn ) ;
effect + + ;
2018-07-18 22:07:48 +02:00
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_MAGNET_RISE :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_MAGNET_RISE )
{
if ( gDisableStructs [ gActiveBattler ] . magnetRiseTimer = = 0 | | - - gDisableStructs [ gActiveBattler ] . magnetRiseTimer = = 0 )
2018-07-18 22:07:48 +02:00
{
2019-08-22 15:57:33 +02:00
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_MAGNET_RISE ) ;
BattleScriptExecute ( BattleScript_BufferEndTurn ) ;
PREPARE_STRING_BUFFER ( gBattleTextBuff1 , STRINGID_ELECTROMAGNETISM ) ;
effect + + ;
2018-07-18 22:07:48 +02:00
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_TELEKINESIS :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_TELEKINESIS )
{
if ( gDisableStructs [ gActiveBattler ] . telekinesisTimer = = 0 | | - - gDisableStructs [ gActiveBattler ] . telekinesisTimer = = 0 )
2018-07-19 21:18:20 +02:00
{
2019-08-22 15:57:33 +02:00
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_TELEKINESIS ) ;
BattleScriptExecute ( BattleScript_TelekinesisEndTurn ) ;
effect + + ;
2018-07-19 21:18:20 +02:00
}
2019-08-22 15:57:33 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_HEALBLOCK :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK )
{
if ( gDisableStructs [ gActiveBattler ] . healBlockTimer = = 0 | | - - gDisableStructs [ gActiveBattler ] . healBlockTimer = = 0 )
2019-04-16 15:01:48 +02:00
{
2019-08-22 15:57:33 +02:00
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_HEAL_BLOCK ) ;
BattleScriptExecute ( BattleScript_BufferEndTurn ) ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_HEAL_BLOCK ) ;
2019-04-16 15:01:48 +02:00
effect + + ;
}
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ROOST : // Return flying type.
if ( gBattleResources - > flags - > flags [ gActiveBattler ] & RESOURCE_FLAG_ROOST )
{
gBattleResources - > flags - > flags [ gActiveBattler ] & = ~ ( RESOURCE_FLAG_ROOST ) ;
gBattleMons [ gActiveBattler ] . type1 = gBattleStruct - > roostTypes [ gActiveBattler ] [ 0 ] ;
gBattleMons [ gActiveBattler ] . type2 = gBattleStruct - > roostTypes [ gActiveBattler ] [ 1 ] ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ELECTRIFY :
2021-10-10 06:13:23 +02:00
gStatuses4 [ gActiveBattler ] & = ~ ( STATUS4_ELECTRIFIED ) ;
2019-08-22 15:57:33 +02:00
gBattleStruct - > turnEffectsTracker + + ;
case ENDTURN_POWDER :
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_POWDER ) ;
gBattleStruct - > turnEffectsTracker + + ;
case ENDTURN_THROAT_CHOP :
if ( gDisableStructs [ gActiveBattler ] . throatChopTimer & & - - gDisableStructs [ gActiveBattler ] . throatChopTimer = = 0 )
{
BattleScriptExecute ( BattleScript_ThroatChopEndTurn ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2020-04-18 12:52:15 +02:00
case ENDTURN_SLOW_START :
if ( gDisableStructs [ gActiveBattler ] . slowStartTimer
& & - - gDisableStructs [ gActiveBattler ] . slowStartTimer = = 0
& & ability = = ABILITY_SLOW_START )
{
BattleScriptExecute ( BattleScript_SlowStartEnds ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2021-10-17 17:27:17 +02:00
case ENDTURN_PLASMA_FISTS :
for ( i = 0 ; i < gBattlersCount ; i + + )
gStatuses4 [ i ] & = ~ ( STATUS4_PLASMA_FISTS ) ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
2019-08-22 15:57:33 +02:00
case ENDTURN_BATTLER_COUNT : // done
gBattleStruct - > turnEffectsTracker = 0 ;
gBattleStruct - > turnEffectsBattlerId + + ;
break ;
2017-09-17 14:10:32 +02:00
}
2019-08-22 15:57:33 +02:00
if ( effect ! = 0 )
return effect ;
2017-09-17 14:10:32 +02:00
}
2021-10-29 15:03:14 +02:00
gHitMarker & = ~ ( HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK ) ;
2017-09-17 14:10:32 +02:00
return 0 ;
}
2017-12-02 14:08:55 +01:00
bool8 HandleWishPerishSongOnTurnEnd ( void )
2017-09-17 14:10:32 +02:00
{
2021-10-29 15:03:14 +02:00
gHitMarker | = ( HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK ) ;
2017-09-17 14:10:32 +02:00
2017-12-02 14:08:55 +01:00
switch ( gBattleStruct - > wishPerishSongState )
2017-09-17 14:10:32 +02:00
{
case 0 :
2018-02-07 22:53:40 +01:00
while ( gBattleStruct - > wishPerishSongBattlerId < gBattlersCount )
2017-09-17 14:10:32 +02:00
{
2018-02-07 22:53:40 +01:00
gActiveBattler = gBattleStruct - > wishPerishSongBattlerId ;
2018-02-06 02:46:59 +01:00
if ( gAbsentBattlerFlags & gBitTable [ gActiveBattler ] )
2017-09-17 14:10:32 +02:00
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > wishPerishSongBattlerId + + ;
2017-09-17 14:10:32 +02:00
continue ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > wishPerishSongBattlerId + + ;
2018-02-06 02:46:59 +01:00
if ( gWishFutureKnock . futureSightCounter [ gActiveBattler ] ! = 0
& & - - gWishFutureKnock . futureSightCounter [ gActiveBattler ] = = 0
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gWishFutureKnock . futureSightMove [ gActiveBattler ] = = MOVE_FUTURE_SIGHT )
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_FUTURE_SIGHT ;
2017-09-17 14:10:32 +02:00
else
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_DOOM_DESIRE ;
2017-09-17 14:10:32 +02:00
2018-02-06 02:46:59 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , gWishFutureKnock . futureSightMove [ gActiveBattler ] ) ;
2017-11-26 13:26:58 +01:00
2018-02-06 23:09:39 +01:00
gBattlerTarget = gActiveBattler ;
gBattlerAttacker = gWishFutureKnock . futureSightAttacker [ gActiveBattler ] ;
2018-02-07 22:53:40 +01:00
gSpecialStatuses [ gBattlerTarget ] . dmg = 0xFFFF ;
2018-12-02 18:47:39 +01:00
gCurrentMove = gWishFutureKnock . futureSightMove [ gActiveBattler ] ;
SetTypeBeforeUsingMove ( gCurrentMove , gActiveBattler ) ;
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_MonTookFutureAttack ) ;
2017-09-17 14:10:32 +02:00
2018-02-06 02:46:59 +01:00
if ( gWishFutureKnock . futureSightCounter [ gActiveBattler ] = = 0
& & gWishFutureKnock . futureSightCounter [ gActiveBattler ^ BIT_FLANK ] = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gSideStatuses [ GET_BATTLER_SIDE ( gBattlerTarget ) ] & = ~ ( SIDE_STATUS_FUTUREATTACK ) ;
2017-09-17 14:10:32 +02:00
}
2017-11-26 13:26:58 +01:00
return TRUE ;
2017-09-17 14:10:32 +02:00
}
}
2018-12-02 18:47:39 +01:00
gBattleStruct - > wishPerishSongState = 1 ;
gBattleStruct - > wishPerishSongBattlerId = 0 ;
2017-09-17 14:10:32 +02:00
// fall through
case 1 :
2018-02-07 22:53:40 +01:00
while ( gBattleStruct - > wishPerishSongBattlerId < gBattlersCount )
2017-09-17 14:10:32 +02:00
{
2018-06-28 21:06:32 +02:00
gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder [ gBattleStruct - > wishPerishSongBattlerId ] ;
2018-02-06 02:46:59 +01:00
if ( gAbsentBattlerFlags & gBitTable [ gActiveBattler ] )
2017-09-17 14:10:32 +02:00
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > wishPerishSongBattlerId + + ;
2017-09-17 14:10:32 +02:00
continue ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > wishPerishSongBattlerId + + ;
2018-02-06 02:46:59 +01:00
if ( gStatuses3 [ gActiveBattler ] & STATUS3_PERISH_SONG )
2017-09-17 14:10:32 +02:00
{
2018-10-14 18:10:54 +02:00
PREPARE_BYTE_NUMBER_BUFFER ( gBattleTextBuff1 , 1 , gDisableStructs [ gActiveBattler ] . perishSongTimer ) ;
if ( gDisableStructs [ gActiveBattler ] . perishSongTimer = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gStatuses3 [ gActiveBattler ] & = ~ STATUS3_PERISH_SONG ;
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . hp ;
2017-11-26 17:26:11 +01:00
gBattlescriptCurrInstr = BattleScript_PerishSongTakesLife ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-10-14 18:10:54 +02:00
gDisableStructs [ gActiveBattler ] . perishSongTimer - - ;
2017-11-26 17:26:11 +01:00
gBattlescriptCurrInstr = BattleScript_PerishSongCountGoesDown ;
2017-09-17 14:10:32 +02:00
}
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-11-26 13:26:58 +01:00
return TRUE ;
2017-09-17 14:10:32 +02:00
}
}
// Hm...
{
2017-12-02 14:08:55 +01:00
u8 * state = & gBattleStruct - > wishPerishSongState ;
* state = 2 ;
2018-02-07 22:53:40 +01:00
gBattleStruct - > wishPerishSongBattlerId = 0 ;
2017-09-17 14:10:32 +02:00
}
// fall through
case 2 :
if ( ( gBattleTypeFlags & BATTLE_TYPE_ARENA )
2018-12-07 23:50:56 +01:00
& & gBattleStruct - > arenaTurnCounter = = 2
2017-09-17 14:10:32 +02:00
& & gBattleMons [ 0 ] . hp ! = 0 & & gBattleMons [ 1 ] . hp ! = 0 )
{
s32 i ;
for ( i = 0 ; i < 2 ; i + + )
CancelMultiTurnMoves ( i ) ;
2018-11-11 18:33:16 +01:00
gBattlescriptCurrInstr = BattleScript_ArenaDoJudgment ;
BattleScriptExecute ( BattleScript_ArenaDoJudgment ) ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongState + + ;
2017-11-26 13:26:58 +01:00
return TRUE ;
2017-09-17 14:10:32 +02:00
}
break ;
}
2021-10-29 15:03:14 +02:00
gHitMarker & = ~ ( HITMARKER_GRUDGE | HITMARKER_SKIP_DMG_TRACK ) ;
2017-09-17 14:10:32 +02:00
2017-11-26 13:26:58 +01:00
return FALSE ;
2017-09-17 14:10:32 +02:00
}
2017-12-02 14:08:55 +01:00
# define FAINTED_ACTIONS_MAX_CASE 7
2017-09-17 14:10:32 +02:00
2017-12-02 14:08:55 +01:00
bool8 HandleFaintedMonActions ( void )
2017-09-17 14:10:32 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
return FALSE ;
do
{
2018-07-01 11:15:42 +02:00
s32 i ;
2017-12-02 14:08:55 +01:00
switch ( gBattleStruct - > faintedActionsState )
2017-09-17 14:10:32 +02:00
{
case 0 :
2018-02-07 22:53:40 +01:00
gBattleStruct - > faintedActionsBattlerId = 0 ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState + + ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-09-17 14:10:32 +02:00
{
2021-04-03 18:38:07 +02:00
if ( gAbsentBattlerFlags & gBitTable [ i ] & & ! HasNoMonsToSwitch ( i , PARTY_SIZE , PARTY_SIZE ) )
2018-02-06 02:46:59 +01:00
gAbsentBattlerFlags & = ~ ( gBitTable [ i ] ) ;
2017-09-17 14:10:32 +02:00
}
// fall through
case 1 :
do
{
2018-02-08 11:17:41 +01:00
gBattlerFainted = gBattlerTarget = gBattleStruct - > faintedActionsBattlerId ;
2018-02-07 22:53:40 +01:00
if ( gBattleMons [ gBattleStruct - > faintedActionsBattlerId ] . hp = = 0
2018-12-07 23:50:56 +01:00
& & ! ( gBattleStruct - > givenExpMons & gBitTable [ gBattlerPartyIndexes [ gBattleStruct - > faintedActionsBattlerId ] ] )
2018-02-07 22:53:40 +01:00
& & ! ( gAbsentBattlerFlags & gBitTable [ gBattleStruct - > faintedActionsBattlerId ] ) )
2017-09-17 14:10:32 +02:00
{
2017-12-02 14:08:55 +01:00
BattleScriptExecute ( BattleScript_GiveExp ) ;
gBattleStruct - > faintedActionsState = 2 ;
2017-09-17 14:10:32 +02:00
return TRUE ;
}
2018-02-07 22:53:40 +01:00
} while ( + + gBattleStruct - > faintedActionsBattlerId ! = gBattlersCount ) ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 3 ;
2017-09-17 14:10:32 +02:00
break ;
case 2 :
2020-07-28 04:22:16 +02:00
OpponentSwitchInResetSentPokesToOpponentValue ( gBattlerFainted ) ;
2018-02-07 22:53:40 +01:00
if ( + + gBattleStruct - > faintedActionsBattlerId = = gBattlersCount )
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 3 ;
2017-09-17 14:10:32 +02:00
else
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 1 ;
2019-08-22 15:57:33 +02:00
// Don't switch mons until all pokemon performed their actions or the battle's over.
if ( gBattleOutcome = = 0
& & ! NoAliveMonsForEitherParty ( )
& & gCurrentTurnActionNumber ! = gBattlersCount )
{
gAbsentBattlerFlags | = gBitTable [ gBattlerFainted ] ;
return FALSE ;
}
2017-09-17 14:10:32 +02:00
break ;
case 3 :
2019-08-26 14:55:55 +02:00
// Don't switch mons until all pokemon performed their actions or the battle's over.
if ( gBattleOutcome = = 0
& & ! NoAliveMonsForEitherParty ( )
& & gCurrentTurnActionNumber ! = gBattlersCount )
{
return FALSE ;
}
2018-02-07 22:53:40 +01:00
gBattleStruct - > faintedActionsBattlerId = 0 ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState + + ;
2017-09-17 14:10:32 +02:00
// fall through
case 4 :
do
{
2018-02-08 11:17:41 +01:00
gBattlerFainted = gBattlerTarget = gBattleStruct - > faintedActionsBattlerId ;
2018-02-07 22:53:40 +01:00
if ( gBattleMons [ gBattleStruct - > faintedActionsBattlerId ] . hp = = 0
& & ! ( gAbsentBattlerFlags & gBitTable [ gBattleStruct - > faintedActionsBattlerId ] ) )
2017-09-17 14:10:32 +02:00
{
2017-12-02 14:08:55 +01:00
BattleScriptExecute ( BattleScript_HandleFaintedMon ) ;
gBattleStruct - > faintedActionsState = 5 ;
2017-09-17 14:10:32 +02:00
return TRUE ;
}
2018-02-07 22:53:40 +01:00
} while ( + + gBattleStruct - > faintedActionsBattlerId ! = gBattlersCount ) ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 6 ;
2017-09-17 14:10:32 +02:00
break ;
case 5 :
2018-02-07 22:53:40 +01:00
if ( + + gBattleStruct - > faintedActionsBattlerId = = gBattlersCount )
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 6 ;
2017-09-17 14:10:32 +02:00
else
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 4 ;
2017-09-17 14:10:32 +02:00
break ;
case 6 :
2019-08-30 12:25:21 +02:00
if ( ItemBattleEffects ( 1 , 0 , TRUE ) )
2017-09-17 14:10:32 +02:00
return TRUE ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState + + ;
2017-09-17 14:10:32 +02:00
break ;
2017-12-02 14:08:55 +01:00
case FAINTED_ACTIONS_MAX_CASE :
2017-09-17 14:10:32 +02:00
break ;
}
2017-12-02 14:08:55 +01:00
} while ( gBattleStruct - > faintedActionsState ! = FAINTED_ACTIONS_MAX_CASE ) ;
2017-09-17 14:10:32 +02:00
return FALSE ;
}
2018-08-11 12:16:00 +02:00
void TryClearRageAndFuryCutter ( void )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
s32 i ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
if ( ( gBattleMons [ i ] . status2 & STATUS2_RAGE ) & & gChosenMoveByBattler [ i ] ! = MOVE_RAGE )
2017-09-17 14:10:32 +02:00
gBattleMons [ i ] . status2 & = ~ ( STATUS2_RAGE ) ;
2018-08-11 12:16:00 +02:00
if ( gDisableStructs [ i ] . furyCutterCounter ! = 0 & & gChosenMoveByBattler [ i ] ! = MOVE_FURY_CUTTER )
gDisableStructs [ i ] . furyCutterCounter = 0 ;
2017-09-17 14:10:32 +02:00
}
}
2018-08-03 00:13:44 +02:00
enum
{
2018-08-03 00:24:10 +02:00
CANCELLER_FLAGS ,
CANCELLER_ASLEEP ,
CANCELLER_FROZEN ,
CANCELLER_TRUANT ,
CANCELLER_RECHARGE ,
CANCELLER_FLINCH ,
CANCELLER_DISABLED ,
2019-04-16 15:01:48 +02:00
CANCELLER_GRAVITY ,
CANCELLER_HEAL_BLOCKED ,
2018-08-03 00:24:10 +02:00
CANCELLER_TAUNTED ,
CANCELLER_IMPRISONED ,
CANCELLER_CONFUSED ,
CANCELLER_PARALYSED ,
CANCELLER_IN_LOVE ,
CANCELLER_BIDE ,
CANCELLER_THAW ,
2019-04-16 15:01:48 +02:00
CANCELLER_POWDER_MOVE ,
CANCELLER_POWDER_STATUS ,
CANCELLER_THROAT_CHOP ,
2018-08-03 00:24:10 +02:00
CANCELLER_END ,
2019-04-16 15:01:48 +02:00
CANCELLER_PSYCHIC_TERRAIN ,
CANCELLER_END2 ,
2018-08-03 00:13:44 +02:00
} ;
2017-09-17 14:10:32 +02:00
u8 AtkCanceller_UnableToUseMove ( void )
{
u8 effect = 0 ;
2017-12-03 00:47:21 +01:00
s32 * bideDmg = & gBattleScripting . bideDmg ;
2017-09-17 14:10:32 +02:00
do
{
switch ( gBattleStruct - > atkCancellerTracker )
{
2018-08-03 00:13:44 +02:00
case CANCELLER_FLAGS : // flags clear
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_DESTINY_BOND ) ;
gStatuses3 [ gBattlerAttacker ] & = ~ ( STATUS3_GRUDGE ) ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_ASLEEP : // check being asleep
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_SLEEP )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
if ( UproarWakeUpCheck ( gBattlerAttacker ) )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status1 & = ~ ( STATUS1_SLEEP ) ;
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_WOKE_UP_UPROAR ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp ;
effect = 2 ;
}
else
{
u8 toSub ;
2021-10-02 23:16:14 +02:00
if ( GetBattlerAbility ( gBattlerAttacker ) = = ABILITY_EARLY_BIRD )
2017-09-17 14:10:32 +02:00
toSub = 2 ;
else
toSub = 1 ;
2018-02-06 23:09:39 +01:00
if ( ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_SLEEP ) < toSub )
gBattleMons [ gBattlerAttacker ] . status1 & = ~ ( STATUS1_SLEEP ) ;
2017-09-17 14:10:32 +02:00
else
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status1 - = toSub ;
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_SLEEP )
2017-09-17 14:10:32 +02:00
{
2021-10-02 14:38:43 +02:00
if ( gChosenMove ! = MOVE_SNORE & & gChosenMove ! = MOVE_SLEEP_TALK )
2017-09-17 14:10:32 +02:00
{
gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 2 ;
}
}
else
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_WOKE_UP ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp ;
effect = 2 ;
}
}
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_FROZEN : // check being frozen
2021-06-19 01:31:46 +02:00
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_FREEZE & & ! ( gBattleMoves [ gCurrentMove ] . flags & FLAG_THAW_USER ) )
2017-09-17 14:10:32 +02:00
{
if ( Random ( ) % 5 )
{
2021-06-19 01:31:46 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen ;
gHitMarker | = HITMARKER_NO_ATTACKSTRING ;
2017-09-17 14:10:32 +02:00
}
else // unfreeze
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status1 & = ~ ( STATUS1_FREEZE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_DEFROSTED ;
2017-09-17 14:10:32 +02:00
}
effect = 2 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_TRUANT : // truant
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( gBattlerAttacker ) = = ABILITY_TRUANT & & gDisableStructs [ gBattlerAttacker ] . truantCounter )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_LOAFING ;
2018-09-29 13:36:33 +02:00
gBattlerAbility = gBattlerAttacker ;
2020-04-18 13:04:28 +02:00
gBattlescriptCurrInstr = BattleScript_TruantLoafingAround ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags | = MOVE_RESULT_MISSED ;
2017-09-17 14:10:32 +02:00
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_RECHARGE : // recharge
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_RECHARGE )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_RECHARGE ) ;
2018-10-14 18:10:54 +02:00
gDisableStructs [ gBattlerAttacker ] . rechargeTimer = 0 ;
2018-02-06 23:09:39 +01:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_FLINCH : // flinch
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_FLINCHED )
2017-09-17 14:10:32 +02:00
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . flinchImmobility = TRUE ;
2018-02-06 23:09:39 +01:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_DISABLED : // disabled move
2018-02-06 23:09:39 +01:00
if ( gDisableStructs [ gBattlerAttacker ] . disabledMove = = gCurrentMove & & gDisableStructs [ gBattlerAttacker ] . disabledMove ! = 0 )
2017-09-17 14:10:32 +02:00
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . usedDisabledMove = TRUE ;
2018-02-06 23:09:39 +01:00
gBattleScripting . battler = gBattlerAttacker ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-02 21:27:28 +02:00
case CANCELLER_HEAL_BLOCKED :
if ( gStatuses3 [ gBattlerAttacker ] & STATUS3_HEAL_BLOCK & & IsHealBlockPreventingMove ( gBattlerAttacker , gCurrentMove ) )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . usedHealBlockedMove = TRUE ;
2018-08-02 21:27:28 +02:00
gBattleScripting . battler = gBattlerAttacker ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case CANCELLER_GRAVITY :
if ( gFieldStatuses & STATUS_FIELD_GRAVITY & & IsGravityPreventingMove ( gCurrentMove ) )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . usedGravityPreventedMove = TRUE ;
2018-08-02 21:27:28 +02:00
gBattleScripting . battler = gBattlerAttacker ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_TAUNTED : // taunt
2018-10-14 18:10:54 +02:00
if ( gDisableStructs [ gBattlerAttacker ] . tauntTimer & & gBattleMoves [ gCurrentMove ] . power = = 0 )
2017-09-17 14:10:32 +02:00
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . usedTauntedMove = TRUE ;
2018-02-06 23:09:39 +01:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_IMPRISONED : // imprisoned
2018-02-06 23:09:39 +01:00
if ( GetImprisonedMovesCount ( gBattlerAttacker , gCurrentMove ) )
2017-09-17 14:10:32 +02:00
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . usedImprisonedMove = TRUE ;
2018-02-06 23:09:39 +01:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_CONFUSED : // confusion
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_CONFUSION )
2017-09-17 14:10:32 +02:00
{
2020-07-17 02:12:12 +02:00
gBattleMons [ gBattlerAttacker ] . status2 - = STATUS2_CONFUSION_TURN ( 1 ) ;
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_CONFUSION )
2017-09-17 14:10:32 +02:00
{
2020-05-24 10:02:58 +02:00
if ( Random ( ) % ( ( B_CONFUSION_SELF_DMG_CHANCE > = GEN_7 ) ? 3 : 2 ) = = 0 ) // confusion dmg
2017-09-17 14:10:32 +02:00
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = TRUE ;
2018-02-06 23:09:39 +01:00
gBattlerTarget = gBattlerAttacker ;
2019-04-02 00:14:01 +02:00
gBattleMoveDamage = CalculateMoveDamage ( MOVE_NONE , gBattlerAttacker , gBattlerAttacker , TYPE_MYSTERY , 40 , FALSE , FALSE , TRUE ) ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg = TRUE ;
2017-09-17 14:10:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
}
2020-05-18 14:51:30 +02:00
else
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = FALSE ;
2020-05-18 14:51:30 +02:00
BattleScriptPushCursor ( ) ;
}
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused ;
}
else // snapped out of confusion
{
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore ;
}
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_PARALYSED : // paralysis
2018-02-06 23:09:39 +01:00
if ( ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_PARALYSIS ) & & ( Random ( ) % 4 ) = = 0 )
2017-09-17 14:10:32 +02:00
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . prlzImmobility = TRUE ;
2017-09-17 14:10:32 +02:00
// This is removed in Emerald for some reason
2018-02-06 23:09:39 +01:00
//CancelMultiTurnMoves(gBattlerAttacker);
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_IN_LOVE : // infatuation
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_INFATUATION )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleScripting . battler = CountTrailingZeroBits ( ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_INFATUATION ) > > 0x10 ) ;
2017-09-17 14:10:32 +02:00
if ( Random ( ) & 1 )
2018-07-01 11:15:42 +02:00
{
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2018-07-01 11:15:42 +02:00
}
2017-09-17 14:10:32 +02:00
else
{
2019-03-05 17:06:29 +01:00
BattleScriptPush ( BattleScript_MoveUsedIsInLoveCantAttack ) ;
2017-09-17 14:10:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . loveImmobility = TRUE ;
2018-02-06 23:09:39 +01:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
}
gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_BIDE : // bide
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_BIDE )
2017-09-17 14:10:32 +02:00
{
2020-07-17 02:12:12 +02:00
gBattleMons [ gBattlerAttacker ] . status2 - = STATUS2_BIDE_TURN ( 1 ) ;
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_BIDE )
2018-07-01 11:15:42 +02:00
{
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_BideStoringEnergy ;
2018-07-01 11:15:42 +02:00
}
2017-09-17 14:10:32 +02:00
else
{
// This is removed in Emerald for some reason
2018-02-06 23:09:39 +01:00
//gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
if ( gTakenDmg [ gBattlerAttacker ] )
2017-09-17 14:10:32 +02:00
{
gCurrentMove = MOVE_BIDE ;
2018-02-06 23:09:39 +01:00
* bideDmg = gTakenDmg [ gBattlerAttacker ] * 2 ;
2018-02-07 22:53:40 +01:00
gBattlerTarget = gTakenDmgByBattler [ gBattlerAttacker ] ;
2018-02-06 23:09:39 +01:00
if ( gAbsentBattlerFlags & gBitTable [ gBattlerTarget ] )
gBattlerTarget = GetMoveTarget ( MOVE_BIDE , 1 ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_BideAttack ;
}
else
2018-07-01 11:15:42 +02:00
{
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack ;
2018-07-01 11:15:42 +02:00
}
2017-09-17 14:10:32 +02:00
}
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_THAW : // move thawing
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_FREEZE )
2017-09-17 14:10:32 +02:00
{
2021-06-10 13:48:18 +02:00
if ( ! ( gBattleMoves [ gCurrentMove ] . effect = = EFFECT_BURN_UP & & ! IS_BATTLER_OF_TYPE ( gBattlerAttacker , TYPE_FIRE ) ) )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status1 & = ~ ( STATUS1_FREEZE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_DEFROSTED_BY_MOVE ;
2017-09-17 14:10:32 +02:00
}
effect = 2 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2019-03-02 13:08:50 +01:00
case CANCELLER_POWDER_MOVE :
2021-03-06 23:00:52 +01:00
if ( ( gBattleMoves [ gCurrentMove ] . flags & FLAG_POWDER ) & & ( gBattlerAttacker ! = gBattlerTarget ) )
2019-03-02 13:08:50 +01:00
{
2020-05-28 10:38:27 +02:00
if ( ( B_POWDER_GRASS > = GEN_6 & & IS_BATTLER_OF_TYPE ( gBattlerTarget , TYPE_GRASS ) )
2019-03-02 13:08:50 +01:00
| | GetBattlerAbility ( gBattlerTarget ) = = ABILITY_OVERCOAT )
{
gBattlerAbility = gBattlerTarget ;
effect = 1 ;
}
2021-10-09 04:05:01 +02:00
else if ( GetBattlerHoldEffect ( gBattlerTarget , TRUE ) = = HOLD_EFFECT_SAFETY_GOGGLES )
2019-03-02 13:08:50 +01:00
{
2021-10-09 04:05:01 +02:00
RecordItemEffectBattle ( gBattlerTarget , HOLD_EFFECT_SAFETY_GOGGLES ) ;
gLastUsedItem = gBattleMons [ gBattlerTarget ] . item ;
2019-03-02 13:08:50 +01:00
effect = 1 ;
}
if ( effect )
gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case CANCELLER_POWDER_STATUS :
2018-12-03 12:50:32 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_POWDER )
{
u32 moveType ;
GET_MOVE_TYPE ( gCurrentMove , moveType ) ;
if ( moveType = = TYPE_FIRE )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . powderSelfDmg = TRUE ;
2018-12-03 12:50:32 +01:00
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 4 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder ;
2019-05-20 10:10:00 +02:00
effect = 1 ;
2018-12-03 12:50:32 +01:00
}
}
gBattleStruct - > atkCancellerTracker + + ;
2017-09-17 14:10:32 +02:00
break ;
2019-05-07 15:26:58 +02:00
case CANCELLER_THROAT_CHOP :
2019-04-16 15:01:48 +02:00
if ( gDisableStructs [ gBattlerAttacker ] . throatChopTimer & & gBattleMoves [ gCurrentMove ] . flags & FLAG_SOUND )
{
2021-09-23 04:29:00 +02:00
gProtectStructs [ gBattlerAttacker ] . usedThroatChopPreventedMove = TRUE ;
2019-04-16 15:01:48 +02:00
CancelMultiTurnMoves ( gBattlerAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2018-08-03 00:13:44 +02:00
case CANCELLER_END :
2017-09-17 14:10:32 +02:00
break ;
}
2018-12-02 17:58:21 +01:00
} while ( gBattleStruct - > atkCancellerTracker ! = CANCELLER_END & & gBattleStruct - > atkCancellerTracker ! = CANCELLER_END2 & & effect = = 0 ) ;
2017-09-17 14:10:32 +02:00
if ( effect = = 2 )
{
2018-02-06 23:09:39 +01:00
gActiveBattler = gBattlerAttacker ;
2018-02-06 20:48:02 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 14:10:32 +02:00
}
return effect ;
}
2017-09-17 15:19:15 +02:00
2018-12-01 11:35:49 +01:00
// After Protean Activation.
u8 AtkCanceller_UnableToUseMove2 ( void )
{
u8 effect = 0 ;
2019-05-07 15:26:58 +02:00
2018-12-01 11:35:49 +01:00
do
{
switch ( gBattleStruct - > atkCancellerTracker )
{
case CANCELLER_END :
gBattleStruct - > atkCancellerTracker + + ;
case CANCELLER_PSYCHIC_TERRAIN :
if ( gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN
2019-02-28 15:02:54 +01:00
& & IsBattlerGrounded ( gBattlerTarget )
2019-02-16 14:54:17 +01:00
& & GetChosenMovePriority ( gBattlerAttacker ) > 0
2018-12-01 11:35:49 +01:00
& & GetBattlerSide ( gBattlerAttacker ) ! = GetBattlerSide ( gBattlerTarget ) )
{
CancelMultiTurnMoves ( gBattlerAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case CANCELLER_END2 :
break ;
}
} while ( gBattleStruct - > atkCancellerTracker ! = CANCELLER_END2 & & effect = = 0 ) ;
return effect ;
}
2018-07-01 11:15:42 +02:00
bool8 HasNoMonsToSwitch ( u8 battler , u8 partyIdBattlerOn1 , u8 partyIdBattlerOn2 )
2017-09-17 15:19:15 +02:00
{
2018-07-01 11:15:42 +02:00
struct Pokemon * party ;
u8 id1 , id2 ;
2017-09-17 15:19:15 +02:00
s32 i ;
2018-07-01 11:15:42 +02:00
2017-09-17 15:19:15 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) )
return FALSE ;
2018-07-01 11:15:42 +02:00
2019-01-27 20:54:34 +01:00
if ( BATTLE_TWO_VS_ONE_OPPONENT & & GetBattlerSide ( battler ) = = B_SIDE_OPPONENT )
{
id2 = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
id1 = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
party = gEnemyParty ;
if ( partyIdBattlerOn1 = = PARTY_SIZE )
partyIdBattlerOn1 = gBattlerPartyIndexes [ id2 ] ;
if ( partyIdBattlerOn2 = = PARTY_SIZE )
partyIdBattlerOn2 = gBattlerPartyIndexes [ id1 ] ;
for ( i = 0 ; i < PARTY_SIZE ; i + + )
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_NONE
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG
& & i ! = partyIdBattlerOn1 & & i ! = partyIdBattlerOn2
& & i ! = * ( gBattleStruct - > monToSwitchIntoId + id2 ) & & i ! = id1 [ gBattleStruct - > monToSwitchIntoId ] )
break ;
}
return ( i = = PARTY_SIZE ) ;
}
else if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
2017-09-17 15:19:15 +02:00
{
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( battler ) = = B_SIDE_PLAYER )
2017-09-17 15:19:15 +02:00
party = gPlayerParty ;
else
party = gEnemyParty ;
2018-07-01 11:15:42 +02:00
id1 = ( ( battler & BIT_FLANK ) / 2 ) ;
for ( i = id1 * 3 ; i < id1 * 3 + 3 ; i + + )
2017-09-17 15:19:15 +02:00
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
2018-07-01 11:15:42 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_NONE
2017-09-17 15:19:15 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
break ;
}
2018-07-01 11:15:42 +02:00
return ( i = = id1 * 3 + 3 ) ;
2017-09-17 15:19:15 +02:00
}
else if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
{
2021-01-13 21:17:32 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_TOWER_LINK_MULTI )
2017-09-17 15:19:15 +02:00
{
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( battler ) = = B_SIDE_PLAYER )
2017-09-17 15:19:15 +02:00
{
party = gPlayerParty ;
2018-07-01 11:15:42 +02:00
id2 = GetBattlerMultiplayerId ( battler ) ;
id1 = GetLinkTrainerFlankId ( id2 ) ;
2017-09-17 15:19:15 +02:00
}
else
{
party = gEnemyParty ;
2020-09-09 02:46:08 +02:00
if ( battler = = 1 )
2018-07-01 11:15:42 +02:00
id1 = 0 ;
else
id1 = 1 ;
2017-09-17 15:19:15 +02:00
}
}
else
{
2018-07-01 11:15:42 +02:00
id2 = GetBattlerMultiplayerId ( battler ) ;
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( battler ) = = B_SIDE_PLAYER )
2017-09-17 15:19:15 +02:00
party = gPlayerParty ;
else
party = gEnemyParty ;
2018-07-01 11:15:42 +02:00
id1 = GetLinkTrainerFlankId ( id2 ) ;
2017-09-17 15:19:15 +02:00
}
2018-07-01 11:15:42 +02:00
for ( i = id1 * 3 ; i < id1 * 3 + 3 ; i + + )
2017-09-17 15:19:15 +02:00
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
2018-07-01 11:15:42 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_NONE
2017-09-17 15:19:15 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
break ;
}
2018-07-01 11:15:42 +02:00
return ( i = = id1 * 3 + 3 ) ;
2017-09-17 15:19:15 +02:00
}
2018-02-06 02:46:59 +01:00
else if ( ( gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS ) & & GetBattlerSide ( battler ) = = B_SIDE_OPPONENT )
2017-09-17 15:19:15 +02:00
{
party = gEnemyParty ;
2018-02-06 02:46:59 +01:00
if ( battler = = 1 )
2018-07-01 11:15:42 +02:00
id1 = 0 ;
2017-09-17 15:19:15 +02:00
else
2018-07-01 11:15:42 +02:00
id1 = 3 ;
for ( i = id1 ; i < id1 + 3 ; i + + )
2017-09-17 15:19:15 +02:00
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
2018-07-01 11:15:42 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_NONE
2017-09-17 15:19:15 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
break ;
}
2018-07-01 11:15:42 +02:00
return ( i = = id1 + 3 ) ;
2017-09-17 15:19:15 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( battler ) = = B_SIDE_OPPONENT )
2017-09-17 15:19:15 +02:00
{
2018-07-01 11:15:42 +02:00
id2 = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
id1 = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
2017-09-17 15:19:15 +02:00
party = gEnemyParty ;
}
else
{
2018-07-01 11:15:42 +02:00
id2 = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
id1 = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
2017-09-17 15:19:15 +02:00
party = gPlayerParty ;
}
2018-07-01 11:15:42 +02:00
if ( partyIdBattlerOn1 = = PARTY_SIZE )
partyIdBattlerOn1 = gBattlerPartyIndexes [ id2 ] ;
if ( partyIdBattlerOn2 = = PARTY_SIZE )
partyIdBattlerOn2 = gBattlerPartyIndexes [ id1 ] ;
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-09-17 15:19:15 +02:00
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
2018-07-01 11:15:42 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_NONE
2017-09-17 15:19:15 +02:00
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG
2018-07-01 11:15:42 +02:00
& & i ! = partyIdBattlerOn1 & & i ! = partyIdBattlerOn2
& & i ! = * ( gBattleStruct - > monToSwitchIntoId + id2 ) & & i ! = id1 [ gBattleStruct - > monToSwitchIntoId ] )
2017-09-17 15:19:15 +02:00
break ;
}
2018-07-01 11:15:42 +02:00
return ( i = = PARTY_SIZE ) ;
2017-09-17 15:19:15 +02:00
}
}
2019-06-15 14:46:35 +02:00
u8 TryWeatherFormChange ( u8 battler )
2017-09-17 15:19:15 +02:00
{
2019-06-15 14:46:35 +02:00
u8 ret = 0 ;
bool32 weatherEffect = WEATHER_HAS_EFFECT ;
2021-05-24 17:52:45 +02:00
u16 holdEffect = GetBattlerHoldEffect ( battler , TRUE ) ;
2019-06-15 14:46:35 +02:00
if ( gBattleMons [ battler ] . species = = SPECIES_CASTFORM )
2017-09-17 15:19:15 +02:00
{
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( battler ) ! = ABILITY_FORECAST | | gBattleMons [ battler ] . hp = = 0 )
2019-06-15 14:46:35 +02:00
{
ret = 0 ;
}
else if ( ! weatherEffect & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_NORMAL ) )
{
SET_BATTLER_TYPE ( battler , TYPE_NORMAL ) ;
ret = 1 ;
}
else if ( ! weatherEffect )
{
ret = 0 ;
}
2021-05-24 17:52:45 +02:00
else if ( holdEffect = = HOLD_EFFECT_UTILITY_UMBRELLA | | ( ! ( gBattleWeather & ( WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL_ANY ) ) & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_NORMAL ) ) )
2019-06-15 14:46:35 +02:00
{
SET_BATTLER_TYPE ( battler , TYPE_NORMAL ) ;
ret = 1 ;
}
2021-05-24 17:52:45 +02:00
else if ( gBattleWeather & WEATHER_SUN_ANY & & holdEffect ! = HOLD_EFFECT_UTILITY_UMBRELLA & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_FIRE ) )
2019-06-15 14:46:35 +02:00
{
SET_BATTLER_TYPE ( battler , TYPE_FIRE ) ;
ret = 2 ;
}
2021-05-24 17:52:45 +02:00
else if ( gBattleWeather & WEATHER_RAIN_ANY & & holdEffect ! = HOLD_EFFECT_UTILITY_UMBRELLA & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_WATER ) )
2019-06-15 14:46:35 +02:00
{
SET_BATTLER_TYPE ( battler , TYPE_WATER ) ;
ret = 3 ;
}
else if ( gBattleWeather & WEATHER_HAIL_ANY & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_ICE ) )
{
SET_BATTLER_TYPE ( battler , TYPE_ICE ) ;
ret = 4 ;
}
2017-09-17 15:19:15 +02:00
}
2019-06-15 14:46:35 +02:00
else if ( gBattleMons [ battler ] . species = = SPECIES_CHERRIM )
2017-09-17 15:19:15 +02:00
{
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( battler ) ! = ABILITY_FLOWER_GIFT | | gBattleMons [ battler ] . hp = = 0 )
2019-06-15 14:46:35 +02:00
ret = 0 ;
2021-05-24 17:52:45 +02:00
else if ( gBattleMonForms [ battler ] = = 0 & & weatherEffect & & holdEffect ! = HOLD_EFFECT_UTILITY_UMBRELLA & & gBattleWeather & WEATHER_SUN_ANY )
2019-06-16 09:30:05 +02:00
ret = 2 ;
2021-11-14 01:31:06 +01:00
else if ( gBattleMonForms [ battler ] ! = 0 & & ( ! weatherEffect | | holdEffect = = HOLD_EFFECT_UTILITY_UMBRELLA | | ! ( gBattleWeather & WEATHER_SUN_ANY ) ) )
2019-06-15 14:46:35 +02:00
ret = 1 ;
2017-09-17 15:19:15 +02:00
}
2019-06-15 14:46:35 +02:00
return ret ;
}
2018-07-27 23:40:10 +02:00
static const u16 sWeatherFlagsInfo [ ] [ 3 ] =
{
[ ENUM_WEATHER_RAIN ] = { WEATHER_RAIN_TEMPORARY , WEATHER_RAIN_PERMANENT , HOLD_EFFECT_DAMP_ROCK } ,
2021-08-26 21:14:05 +02:00
[ ENUM_WEATHER_RAIN_PRIMAL ] = { WEATHER_RAIN_PRIMAL , WEATHER_RAIN_PRIMAL , HOLD_EFFECT_DAMP_ROCK } ,
2018-07-27 23:40:10 +02:00
[ ENUM_WEATHER_SUN ] = { WEATHER_SUN_TEMPORARY , WEATHER_SUN_PERMANENT , HOLD_EFFECT_HEAT_ROCK } ,
2021-08-26 21:14:05 +02:00
[ ENUM_WEATHER_SUN_PRIMAL ] = { WEATHER_SUN_PRIMAL , WEATHER_SUN_PRIMAL , HOLD_EFFECT_HEAT_ROCK } ,
2018-07-27 23:40:10 +02:00
[ ENUM_WEATHER_SANDSTORM ] = { WEATHER_SANDSTORM_TEMPORARY , WEATHER_SANDSTORM_PERMANENT , HOLD_EFFECT_SMOOTH_ROCK } ,
[ ENUM_WEATHER_HAIL ] = { WEATHER_HAIL_TEMPORARY , WEATHER_HAIL_PERMANENT , HOLD_EFFECT_ICY_ROCK } ,
2021-08-26 21:14:05 +02:00
[ ENUM_WEATHER_STRONG_WINDS ] = { WEATHER_STRONG_WINDS , WEATHER_STRONG_WINDS , HOLD_EFFECT_NONE } ,
2018-07-27 23:40:10 +02:00
} ;
bool32 TryChangeBattleWeather ( u8 battler , u32 weatherEnumId , bool32 viaAbility )
{
if ( viaAbility & & B_ABILITY_WEATHER < = GEN_5
& & ! ( gBattleWeather & sWeatherFlagsInfo [ weatherEnumId ] [ 1 ] ) )
2017-09-17 15:19:15 +02:00
{
2018-07-27 23:40:10 +02:00
gBattleWeather = ( sWeatherFlagsInfo [ weatherEnumId ] [ 0 ] | sWeatherFlagsInfo [ weatherEnumId ] [ 1 ] ) ;
return TRUE ;
2017-09-17 15:19:15 +02:00
}
2021-08-26 21:14:05 +02:00
else if ( gBattleWeather & WEATHER_PRIMAL_ANY
& & GetBattlerAbility ( battler ) ! = ABILITY_DESOLATE_LAND
& & GetBattlerAbility ( battler ) ! = ABILITY_PRIMORDIAL_SEA
& & GetBattlerAbility ( battler ) ! = ABILITY_DELTA_STREAM )
{
2021-10-06 14:10:56 +02:00
return FALSE ;
2021-08-26 21:14:05 +02:00
}
2019-10-26 18:28:02 +02:00
else if ( ! ( gBattleWeather & ( sWeatherFlagsInfo [ weatherEnumId ] [ 0 ] | sWeatherFlagsInfo [ weatherEnumId ] [ 1 ] ) ) )
2017-09-17 15:19:15 +02:00
{
2018-07-27 23:40:10 +02:00
gBattleWeather = ( sWeatherFlagsInfo [ weatherEnumId ] [ 0 ] ) ;
if ( GetBattlerHoldEffect ( battler , TRUE ) = = sWeatherFlagsInfo [ weatherEnumId ] [ 2 ] )
gWishFutureKnock . weatherDuration = 8 ;
else
gWishFutureKnock . weatherDuration = 5 ;
return TRUE ;
2017-09-17 15:19:15 +02:00
}
2019-02-09 14:30:16 +01:00
return FALSE ;
2017-09-17 15:19:15 +02:00
}
2019-02-09 14:30:16 +01:00
static bool32 TryChangeBattleTerrain ( u32 battler , u32 statusFlag , u8 * timer )
2017-09-17 15:19:15 +02:00
{
2019-02-09 14:30:16 +01:00
if ( ! ( gFieldStatuses & statusFlag ) )
2017-09-17 15:19:15 +02:00
{
2019-02-09 14:30:16 +01:00
gFieldStatuses & = ~ ( STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | EFFECT_ELECTRIC_TERRAIN | EFFECT_PSYCHIC_TERRAIN ) ;
gFieldStatuses | = statusFlag ;
2017-09-17 15:19:15 +02:00
2019-02-09 14:30:16 +01:00
if ( GetBattlerHoldEffect ( battler , TRUE ) = = HOLD_EFFECT_TERRAIN_EXTENDER )
* timer = 8 ;
2017-09-17 15:19:15 +02:00
else
2019-02-09 14:30:16 +01:00
* timer = 5 ;
2017-09-17 15:19:15 +02:00
2019-02-09 14:30:16 +01:00
gBattlerAttacker = gBattleScripting . battler = battler ;
return TRUE ;
2018-07-27 23:40:10 +02:00
}
2019-02-09 14:30:16 +01:00
return FALSE ;
2018-07-27 23:40:10 +02:00
}
2017-09-17 15:19:15 +02:00
2020-04-19 21:18:39 +02:00
static bool32 ShouldChangeFormHpBased ( u32 battler )
{
2020-04-21 20:43:47 +02:00
// Ability, form >, form <=, hp divided
static const u16 forms [ ] [ 4 ] =
2020-04-19 21:18:39 +02:00
{
2020-11-15 17:35:02 +01:00
{ ABILITY_ZEN_MODE , SPECIES_DARMANITAN , SPECIES_DARMANITAN_ZEN_MODE , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR , SPECIES_MINIOR_CORE_RED , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR_METEOR_BLUE , SPECIES_MINIOR_CORE_BLUE , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR_METEOR_GREEN , SPECIES_MINIOR_CORE_GREEN , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR_METEOR_INDIGO , SPECIES_MINIOR_CORE_INDIGO , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR_METEOR_ORANGE , SPECIES_MINIOR_CORE_ORANGE , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR_METEOR_VIOLET , SPECIES_MINIOR_CORE_VIOLET , 2 } ,
{ ABILITY_SHIELDS_DOWN , SPECIES_MINIOR_METEOR_YELLOW , SPECIES_MINIOR_CORE_YELLOW , 2 } ,
2020-04-21 20:43:47 +02:00
{ ABILITY_SCHOOLING , SPECIES_WISHIWASHI_SCHOOL , SPECIES_WISHIWASHI , 4 } ,
2021-01-12 18:58:24 +01:00
{ ABILITY_GULP_MISSILE , SPECIES_CRAMORANT , SPECIES_CRAMORANT_GORGING , 2 } ,
{ ABILITY_GULP_MISSILE , SPECIES_CRAMORANT , SPECIES_CRAMORANT_GULPING , 1 } ,
2020-04-19 21:18:39 +02:00
} ;
u32 i ;
2017-09-17 15:19:15 +02:00
2020-04-19 21:18:39 +02:00
for ( i = 0 ; i < ARRAY_COUNT ( forms ) ; i + + )
{
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( battler ) = = forms [ i ] [ 0 ] )
2017-09-17 15:19:15 +02:00
{
2020-04-19 21:18:39 +02:00
if ( gBattleMons [ battler ] . species = = forms [ i ] [ 2 ]
2020-04-21 20:43:47 +02:00
& & gBattleMons [ battler ] . hp > gBattleMons [ battler ] . maxHP / forms [ i ] [ 3 ] )
2017-09-18 23:44:55 +02:00
{
2020-04-19 21:18:39 +02:00
gBattleMons [ battler ] . species = forms [ i ] [ 1 ] ;
return TRUE ;
}
if ( gBattleMons [ battler ] . species = = forms [ i ] [ 1 ]
2020-04-21 20:43:47 +02:00
& & gBattleMons [ battler ] . hp < = gBattleMons [ battler ] . maxHP / forms [ i ] [ 3 ] )
2020-04-19 21:18:39 +02:00
{
gBattleMons [ battler ] . species = forms [ i ] [ 2 ] ;
return TRUE ;
}
}
}
return FALSE ;
}
2020-04-28 15:36:13 +02:00
static u8 ForewarnChooseMove ( u32 battler )
{
struct Forewarn {
u8 battlerId ;
u8 power ;
u16 moveId ;
} ;
u32 i , j , bestId , count ;
struct Forewarn * data = malloc ( sizeof ( struct Forewarn ) * MAX_BATTLERS_COUNT * MAX_MON_MOVES ) ;
// Put all moves
for ( count = 0 , i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
{
if ( IsBattlerAlive ( i ) & & GetBattlerSide ( i ) ! = GetBattlerSide ( battler ) )
{
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
{
if ( gBattleMons [ i ] . moves [ j ] = = MOVE_NONE )
continue ;
data [ count ] . moveId = gBattleMons [ i ] . moves [ j ] ;
data [ count ] . battlerId = i ;
switch ( gBattleMoves [ data [ count ] . moveId ] . effect )
2017-09-18 23:44:55 +02:00
{
2020-04-28 15:36:13 +02:00
case EFFECT_OHKO :
data [ count ] . power = 150 ;
break ;
case EFFECT_COUNTER :
case EFFECT_MIRROR_COAT :
case EFFECT_METAL_BURST :
data [ count ] . power = 120 ;
break ;
default :
if ( gBattleMoves [ data [ count ] . moveId ] . power = = 1 )
data [ count ] . power = 80 ;
else
data [ count ] . power = gBattleMoves [ data [ count ] . moveId ] . power ;
break ;
2017-09-18 23:44:55 +02:00
}
2020-04-28 15:36:13 +02:00
count + + ;
2017-09-18 23:44:55 +02:00
}
2020-04-28 15:36:13 +02:00
}
}
for ( bestId = 0 , i = 1 ; i < count ; i + + )
{
if ( data [ i ] . power > data [ bestId ] . power )
bestId = i ;
else if ( data [ i ] . power = = data [ bestId ] . power & & Random ( ) & 1 )
bestId = i ;
}
gBattlerTarget = data [ bestId ] . battlerId ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , data [ bestId ] . moveId )
2020-07-15 21:30:24 +02:00
RecordKnownMove ( gBattlerTarget , data [ bestId ] . moveId ) ;
2020-04-28 15:36:13 +02:00
free ( data ) ;
}
2020-05-18 23:54:12 +02:00
u8 AbilityBattleEffects ( u8 caseID , u8 battler , u16 ability , u8 special , u16 moveArg )
2017-09-17 15:19:15 +02:00
{
u8 effect = 0 ;
2018-07-22 18:40:18 +02:00
u32 speciesAtk , speciesDef ;
u32 pidAtk , pidDef ;
2019-08-30 12:25:21 +02:00
u32 moveType , move ;
2020-04-11 12:34:53 +02:00
u32 i , j ;
2018-07-22 18:40:18 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
2019-01-27 11:47:36 +01:00
return 0 ;
2017-09-17 15:19:15 +02:00
2018-02-06 23:09:39 +01:00
if ( gBattlerAttacker > = gBattlersCount )
gBattlerAttacker = battler ;
2018-07-01 11:15:42 +02:00
2018-07-22 18:40:18 +02:00
speciesAtk = gBattleMons [ gBattlerAttacker ] . species ;
pidAtk = gBattleMons [ gBattlerAttacker ] . personality ;
2017-09-17 15:19:15 +02:00
2018-07-22 18:40:18 +02:00
speciesDef = gBattleMons [ gBattlerTarget ] . species ;
pidDef = gBattleMons [ gBattlerTarget ] . personality ;
2018-07-01 11:15:42 +02:00
2018-11-23 23:07:02 +01:00
if ( special )
gLastUsedAbility = special ;
else
gLastUsedAbility = GetBattlerAbility ( battler ) ;
2017-09-17 15:19:15 +02:00
2018-07-22 18:40:18 +02:00
if ( moveArg )
move = moveArg ;
else
move = gCurrentMove ;
2017-09-17 15:19:15 +02:00
2018-07-22 18:40:18 +02:00
GET_MOVE_TYPE ( move , moveType ) ;
2017-09-17 15:19:15 +02:00
2018-07-22 18:40:18 +02:00
switch ( caseID )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
case ABILITYEFFECT_ON_SWITCHIN : // 0
2020-07-28 10:18:44 +02:00
gBattleScripting . battler = battler ;
2018-07-22 18:40:18 +02:00
switch ( gLastUsedAbility )
2017-09-17 15:19:15 +02:00
{
2020-12-14 03:42:48 +01:00
case ABILITYEFFECT_SWITCH_IN_TERRAIN :
2021-07-25 16:22:05 +02:00
if ( VarGet ( VAR_TERRAIN ) & STATUS_FIELD_TERRAIN_ANY )
2020-12-14 03:42:48 +01:00
{
2021-07-25 16:22:05 +02:00
u16 terrainFlags = VarGet ( VAR_TERRAIN ) & STATUS_FIELD_TERRAIN_ANY ; // only works for status flag (1 << 15)
2020-12-14 03:42:48 +01:00
gFieldStatuses = terrainFlags | STATUS_FIELD_TERRAIN_PERMANENT ; // terrain is permanent
2021-07-25 16:22:05 +02:00
switch ( VarGet ( VAR_TERRAIN ) & STATUS_FIELD_TERRAIN_ANY )
2020-12-14 03:42:48 +01:00
{
case STATUS_FIELD_ELECTRIC_TERRAIN :
gBattleCommunication [ MULTISTRING_CHOOSER ] = 2 ;
break ;
case STATUS_FIELD_MISTY_TERRAIN :
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
break ;
case STATUS_FIELD_GRASSY_TERRAIN :
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
break ;
case STATUS_FIELD_PSYCHIC_TERRAIN :
gBattleCommunication [ MULTISTRING_CHOOSER ] = 3 ;
break ;
}
2021-06-10 12:55:05 +02:00
2020-12-14 03:42:48 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_OverworldTerrain ) ;
effect + + ;
}
# if B_THUNDERSTORM_TERRAIN == TRUE
else if ( GetCurrentWeather ( ) = = WEATHER_RAIN_THUNDERSTORM & & ! ( gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN ) )
{
2021-01-13 22:32:14 +01:00
// overworld weather started rain, so just do electric terrain anim
2020-12-14 03:42:48 +01:00
gFieldStatuses = ( STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT ) ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 2 ;
BattleScriptPushCursorAndCallback ( BattleScript_OverworldTerrain ) ;
effect + + ;
}
# endif
break ;
2018-07-22 18:40:18 +02:00
case ABILITYEFFECT_SWITCH_IN_WEATHER :
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED ) )
2017-09-17 15:19:15 +02:00
{
2018-12-22 13:53:07 +01:00
switch ( GetCurrentWeather ( ) )
2017-09-17 15:19:15 +02:00
{
2019-12-09 08:16:18 +01:00
case WEATHER_RAIN :
case WEATHER_RAIN_THUNDERSTORM :
case WEATHER_DOWNPOUR :
2018-07-22 18:40:18 +02:00
if ( ! ( gBattleWeather & WEATHER_RAIN_ANY ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleWeather = ( WEATHER_RAIN_TEMPORARY | WEATHER_RAIN_PERMANENT ) ;
gBattleScripting . animArg1 = B_ANIM_RAIN_CONTINUES ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2018-12-22 13:53:07 +01:00
case WEATHER_SANDSTORM :
2018-07-22 18:40:18 +02:00
if ( ! ( gBattleWeather & WEATHER_SANDSTORM_ANY ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleWeather = ( WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY ) ;
gBattleScripting . animArg1 = B_ANIM_SANDSTORM_CONTINUES ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2018-12-22 13:53:07 +01:00
case WEATHER_DROUGHT :
2018-07-22 18:40:18 +02:00
if ( ! ( gBattleWeather & WEATHER_SUN_ANY ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleWeather = ( WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY ) ;
gBattleScripting . animArg1 = B_ANIM_SUN_CONTINUES ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
}
}
2018-07-22 18:40:18 +02:00
if ( effect )
{
2018-12-22 13:53:07 +01:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = GetCurrentWeather ( ) ;
2018-07-22 18:40:18 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_OverworldWeatherStarts ) ;
}
2017-09-17 15:19:15 +02:00
break ;
2018-07-29 12:21:28 +02:00
case ABILITY_IMPOSTER :
if ( IsBattlerAlive ( BATTLE_OPPOSITE ( battler ) )
& & ! ( gBattleMons [ BATTLE_OPPOSITE ( battler ) ] . status2 & ( STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE ) )
2019-03-30 11:56:15 +01:00
& & ! ( gBattleMons [ battler ] . status2 & STATUS2_TRANSFORMED )
2020-06-29 13:45:27 +02:00
& & ! ( gBattleStruct - > illusion [ BATTLE_OPPOSITE ( battler ) ] . on )
2019-03-30 11:56:15 +01:00
& & ! ( gStatuses3 [ BATTLE_OPPOSITE ( battler ) ] & STATUS3_SEMI_INVULNERABLE ) )
2018-07-29 12:21:28 +02:00
{
2021-06-10 13:45:24 +02:00
gBattlerAttacker = battler ;
2018-07-29 12:21:28 +02:00
gBattlerTarget = BATTLE_OPPOSITE ( battler ) ;
BattleScriptPushCursorAndCallback ( BattleScript_ImposterActivates ) ;
effect + + ;
}
break ;
2018-07-22 22:21:47 +02:00
case ABILITY_MOLD_BREAKER :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_MOLDBREAKER ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2018-07-22 22:21:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_TERAVOLT :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_TERAVOLT ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2018-07-22 22:21:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_TURBOBLAZE :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_TURBOBLAZE ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2018-07-22 22:21:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_SLOW_START :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2020-04-18 12:52:15 +02:00
gDisableStructs [ battler ] . slowStartTimer = 5 ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_SLOWSTART ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2018-07-22 22:21:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
2017-09-17 15:19:15 +02:00
break ;
2018-07-22 22:21:47 +02:00
case ABILITY_UNNERVE :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
2017-09-17 15:19:15 +02:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_UNNERVE ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2018-07-22 22:21:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
2021-01-06 03:37:23 +01:00
case ABILITY_AS_ONE_ICE_RIDER :
case ABILITY_AS_ONE_SHADOW_RIDER :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_ASONE ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2021-02-02 17:00:07 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_ActivateAsOne ) ;
2021-01-06 03:37:23 +01:00
effect + + ;
}
break ;
2021-01-06 04:02:11 +01:00
case ABILITY_CURIOUS_MEDICINE :
2021-02-02 17:00:07 +01:00
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone & & IsDoubleBattle ( )
& & IsBattlerAlive ( BATTLE_PARTNER ( battler ) ) & & TryResetBattlerStatChanges ( BATTLE_PARTNER ( battler ) ) )
2021-01-06 04:02:11 +01:00
{
u32 i ;
gEffectBattler = BATTLE_PARTNER ( battler ) ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_CURIOUS_MEDICINE ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2021-01-06 04:02:11 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
2021-11-02 11:06:10 +01:00
case ABILITY_PASTEL_VEIL :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-11-02 23:51:20 +01:00
gBattlerTarget = battler ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_PASTEL_VEIL ;
BattleScriptPushCursorAndCallback ( BattleScript_PastelVeilActivates ) ;
effect + + ;
2021-11-02 11:06:10 +01:00
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
}
break ;
2020-04-11 12:24:25 +02:00
case ABILITY_ANTICIPATION :
2020-04-11 12:34:53 +02:00
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
2020-04-11 12:24:25 +02:00
{
2020-04-11 12:34:53 +02:00
u32 side = GetBattlerSide ( battler ) ;
2020-04-11 12:24:25 +02:00
2020-04-11 12:34:53 +02:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2017-09-17 15:19:15 +02:00
{
2020-04-11 12:34:53 +02:00
if ( IsBattlerAlive ( i ) & & side ! = GetBattlerSide ( i ) )
2020-04-11 12:24:25 +02:00
{
2020-04-11 12:34:53 +02:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
2020-04-11 12:24:25 +02:00
{
2020-04-11 12:34:53 +02:00
move = gBattleMons [ i ] . moves [ j ] ;
GET_MOVE_TYPE ( move , moveType ) ;
if ( CalcTypeEffectivenessMultiplier ( move , moveType , i , battler , FALSE ) > = UQ_4_12 ( 2.0 ) )
{
effect + + ;
break ;
}
2020-04-11 12:24:25 +02:00
}
}
2017-09-17 15:19:15 +02:00
}
2020-04-11 12:34:53 +02:00
if ( effect )
2017-09-17 15:19:15 +02:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_ANTICIPATION ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-04-11 12:24:25 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
2017-09-17 15:19:15 +02:00
}
}
break ;
2020-04-19 13:37:56 +02:00
case ABILITY_FRISK :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-04-19 13:37:56 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_FriskActivates ) ; // Try activate
effect + + ;
}
return effect ; // Note: It returns effect as to not record the ability if Frisk does not activate.
2020-04-28 15:36:13 +02:00
case ABILITY_FOREWARN :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
ForewarnChooseMove ( battler ) ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_FOREWARN ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-04-28 15:36:13 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_DOWNLOAD :
2018-07-22 22:21:47 +02:00
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
2017-09-17 15:19:15 +02:00
{
2019-02-09 13:30:45 +01:00
u32 statId , opposingBattler ;
u32 opposingDef = 0 , opposingSpDef = 0 ;
opposingBattler = BATTLE_OPPOSITE ( battler ) ;
2021-09-22 01:53:44 +02:00
for ( i = 0 ; i < 2 ; opposingBattler ^ = BIT_FLANK , i + + )
2017-09-17 15:19:15 +02:00
{
2019-02-09 13:30:45 +01:00
if ( IsBattlerAlive ( opposingBattler ) )
2017-09-17 15:19:15 +02:00
{
2019-02-09 13:30:45 +01:00
opposingDef + = gBattleMons [ opposingBattler ] . defense
* gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_DEF ] ] [ 0 ]
/ gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_DEF ] ] [ 1 ] ;
opposingSpDef + = gBattleMons [ opposingBattler ] . spDefense
* gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_SPDEF ] ] [ 0 ]
/ gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_SPDEF ] ] [ 1 ] ;
2017-09-17 15:19:15 +02:00
}
}
2017-10-12 17:49:24 +02:00
2019-02-09 13:30:45 +01:00
if ( opposingDef < opposingSpDef )
2018-07-22 18:40:18 +02:00
statId = STAT_ATK ;
2019-02-09 13:30:45 +01:00
else
statId = STAT_SPATK ;
2017-10-12 17:49:24 +02:00
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2017-10-12 17:49:24 +02:00
2021-09-03 19:13:02 +02:00
if ( CompareStat ( battler , statId , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleMons [ battler ] . statStages [ statId ] + + ;
SET_STATCHANGER ( statId , 1 , FALSE ) ;
2021-09-22 01:53:44 +02:00
gBattlerAttacker = battler ;
2018-07-22 18:40:18 +02:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , statId ) ;
BattleScriptPushCursorAndCallback ( BattleScript_AttackerAbilityStatRaiseEnd3 ) ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
}
break ;
2020-11-19 19:42:00 +01:00
case ABILITY_PRESSURE :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_PRESSURE ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_DARK_AURA :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_DARKAURA ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_FAIRY_AURA :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_FAIRYAURA ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_AURA_BREAK :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_AURABREAK ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_COMATOSE :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_COMATOSE ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_SCREEN_CLEANER :
2021-01-05 23:44:12 +01:00
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone & & TryRemoveScreens ( battler ) )
2020-11-19 19:42:00 +01:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_SWITCHIN_SCREENCLEANER ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_DRIZZLE :
2018-07-27 23:40:10 +02:00
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_RAIN , TRUE ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_DrizzleActivates ) ;
effect + + ;
}
2021-10-06 14:10:56 +02:00
else if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_PRIMAL_ANY & & ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_BlockedByPrimalWeatherEnd3 ) ;
effect + + ;
}
2018-07-22 18:40:18 +02:00
break ;
case ABILITY_SAND_STREAM :
2018-07-27 23:40:10 +02:00
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_SANDSTORM , TRUE ) )
2018-07-22 18:40:18 +02:00
{
2019-01-19 11:22:49 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_SandstreamActivates ) ;
2018-07-22 18:40:18 +02:00
effect + + ;
}
2021-10-06 14:10:56 +02:00
else if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_PRIMAL_ANY & & ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_BlockedByPrimalWeatherEnd3 ) ;
effect + + ;
}
2018-07-22 18:40:18 +02:00
break ;
case ABILITY_DROUGHT :
2018-07-27 23:40:10 +02:00
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_SUN , TRUE ) )
2018-07-22 18:40:18 +02:00
{
BattleScriptPushCursorAndCallback ( BattleScript_DroughtActivates ) ;
effect + + ;
}
2021-10-06 14:10:56 +02:00
else if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_PRIMAL_ANY & & ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_BlockedByPrimalWeatherEnd3 ) ;
effect + + ;
}
2018-07-22 18:40:18 +02:00
break ;
2018-07-27 23:40:10 +02:00
case ABILITY_SNOW_WARNING :
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_HAIL , TRUE ) )
{
BattleScriptPushCursorAndCallback ( BattleScript_SnowWarningActivates ) ;
effect + + ;
}
2021-10-06 14:10:56 +02:00
else if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_PRIMAL_ANY & & ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_BlockedByPrimalWeatherEnd3 ) ;
effect + + ;
}
2018-07-27 23:40:10 +02:00
break ;
2019-02-09 14:30:16 +01:00
case ABILITY_ELECTRIC_SURGE :
2021-11-06 23:46:52 +01:00
if ( TryChangeBattleTerrain ( battler , STATUS_FIELD_ELECTRIC_TERRAIN , & gFieldTimers . terrainTimer ) )
2019-02-09 14:30:16 +01:00
{
BattleScriptPushCursorAndCallback ( BattleScript_ElectricSurgeActivates ) ;
effect + + ;
}
break ;
case ABILITY_GRASSY_SURGE :
2021-11-06 23:46:52 +01:00
if ( TryChangeBattleTerrain ( battler , STATUS_FIELD_GRASSY_TERRAIN , & gFieldTimers . terrainTimer ) )
2019-02-09 14:30:16 +01:00
{
BattleScriptPushCursorAndCallback ( BattleScript_GrassySurgeActivates ) ;
effect + + ;
}
break ;
case ABILITY_MISTY_SURGE :
2021-11-06 23:46:52 +01:00
if ( TryChangeBattleTerrain ( battler , STATUS_FIELD_MISTY_TERRAIN , & gFieldTimers . terrainTimer ) )
2019-02-09 14:30:16 +01:00
{
BattleScriptPushCursorAndCallback ( BattleScript_MistySurgeActivates ) ;
effect + + ;
}
break ;
case ABILITY_PSYCHIC_SURGE :
2021-11-06 23:46:52 +01:00
if ( TryChangeBattleTerrain ( battler , STATUS_FIELD_PSYCHIC_TERRAIN , & gFieldTimers . terrainTimer ) )
2019-02-09 14:30:16 +01:00
{
BattleScriptPushCursorAndCallback ( BattleScript_PsychicSurgeActivates ) ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_INTIMIDATE :
if ( ! ( gSpecialStatuses [ battler ] . intimidatedMon ) )
{
2019-02-25 16:17:23 +01:00
gBattleResources - > flags - > flags [ battler ] | = RESOURCE_FLAG_INTIMIDATED ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . intimidatedMon = TRUE ;
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITY_FORECAST :
2019-06-15 14:46:35 +02:00
case ABILITY_FLOWER_GIFT :
effect = TryWeatherFormChange ( battler ) ;
2018-07-22 18:40:18 +02:00
if ( effect ! = 0 )
{
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
}
break ;
case ABILITY_TRACE :
if ( ! ( gSpecialStatuses [ battler ] . traced ) )
{
2019-02-25 16:17:23 +01:00
gBattleResources - > flags - > flags [ battler ] | = RESOURCE_FLAG_TRACED ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . traced = TRUE ;
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITY_CLOUD_NINE :
case ABILITY_AIR_LOCK :
2020-11-19 19:42:00 +01:00
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
2018-07-22 18:40:18 +02:00
{
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-11-19 19:42:00 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_AnnounceAirLockCloudNine ) ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2020-04-21 20:43:47 +02:00
case ABILITY_SCHOOLING :
if ( gBattleMons [ battler ] . level < 20 )
break ;
2020-04-19 21:18:39 +02:00
case ABILITY_SHIELDS_DOWN :
if ( ShouldChangeFormHpBased ( battler ) )
{
BattleScriptPushCursorAndCallback ( BattleScript_AttackerFormChangeEnd3 ) ;
effect + + ;
}
break ;
2020-12-02 22:46:29 +01:00
case ABILITY_INTREPID_SWORD :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-12-02 22:46:29 +01:00
SET_STATCHANGER ( STAT_ATK , 1 , FALSE ) ;
2020-12-05 17:50:47 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_BattlerAbilityStatRaiseOnSwitchIn ) ;
2020-12-02 22:46:29 +01:00
effect + + ;
}
break ;
case ABILITY_DAUNTLESS_SHIELD :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = TRUE ;
2020-12-02 22:46:29 +01:00
SET_STATCHANGER ( STAT_DEF , 1 , FALSE ) ;
2020-12-05 17:50:47 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_BattlerAbilityStatRaiseOnSwitchIn ) ;
2020-12-02 22:46:29 +01:00
effect + + ;
}
break ;
2021-08-26 21:14:05 +02:00
case ABILITY_DESOLATE_LAND :
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_SUN_PRIMAL , TRUE ) )
{
BattleScriptPushCursorAndCallback ( BattleScript_DesolateLandActivates ) ;
effect + + ;
}
break ;
case ABILITY_PRIMORDIAL_SEA :
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_RAIN_PRIMAL , TRUE ) )
{
BattleScriptPushCursorAndCallback ( BattleScript_PrimordialSeaActivates ) ;
effect + + ;
}
break ;
case ABILITY_DELTA_STREAM :
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_STRONG_WINDS , TRUE ) )
{
BattleScriptPushCursorAndCallback ( BattleScript_DeltaStreamActivates ) ;
effect + + ;
}
break ;
2021-10-31 01:40:05 +02:00
case ABILITY_MIMICRY :
if ( gBattleMons [ battler ] . hp ! = 0 & & gFieldStatuses & STATUS_FIELD_TERRAIN_ANY )
{
TryToApplyMimicry ( battler , FALSE ) ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_ENDTURN : // 1
if ( gBattleMons [ battler ] . hp ! = 0 )
{
gBattlerAttacker = battler ;
2017-09-17 15:19:15 +02:00
switch ( gLastUsedAbility )
{
2018-07-28 17:13:47 +02:00
case ABILITY_HARVEST :
2021-05-24 17:52:45 +02:00
if ( ( IsBattlerWeatherAffected ( battler , WEATHER_SUN_ANY ) | | Random ( ) % 2 = = 0 )
2018-07-28 17:13:47 +02:00
& & gBattleMons [ battler ] . item = = ITEM_NONE
2021-10-28 23:52:52 +02:00
& & gBattleStruct - > changedItems [ battler ] = = ITEM_NONE // Will not inherit an item
& & ItemId_GetPocket ( GetUsedHeldItem ( battler ) ) = = POCKET_BERRIES )
2017-09-17 15:19:15 +02:00
{
2018-07-28 17:13:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_HarvestActivates ) ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-07-11 14:25:57 +02:00
case ABILITY_DRY_SKIN :
2021-05-24 17:52:45 +02:00
if ( IsBattlerWeatherAffected ( battler , WEATHER_SUN_ANY ) )
2020-07-11 14:25:57 +02:00
goto SOLAR_POWER_HP_DROP ;
// Dry Skin works similarly to Rain Dish in Rain
2018-07-22 18:40:18 +02:00
case ABILITY_RAIN_DISH :
2021-05-24 17:52:45 +02:00
if ( IsBattlerWeatherAffected ( battler , WEATHER_RAIN_ANY )
2018-07-31 23:09:47 +02:00
& & ! BATTLER_MAX_HP ( battler )
& & ! ( gStatuses3 [ battler ] & STATUS3_HEAL_BLOCK ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_RainDishActivates ) ;
2020-07-11 14:25:57 +02:00
gBattleMoveDamage = gBattleMons [ battler ] . maxHP / ( gLastUsedAbility = = ABILITY_RAIN_DISH ? 16 : 8 ) ;
2017-09-17 15:19:15 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-07-22 18:40:18 +02:00
gBattleMoveDamage * = - 1 ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2018-07-22 19:34:13 +02:00
case ABILITY_HYDRATION :
2021-05-24 17:52:45 +02:00
if ( IsBattlerWeatherAffected ( battler , WEATHER_RAIN_ANY )
2018-07-22 19:34:13 +02:00
& & gBattleMons [ battler ] . status1 & STATUS1_ANY )
2017-09-17 15:19:15 +02:00
{
2018-07-22 19:34:13 +02:00
goto ABILITY_HEAL_MON_STATUS ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_SHED_SKIN :
if ( ( gBattleMons [ battler ] . status1 & STATUS1_ANY ) & & ( Random ( ) % 3 ) = = 0 )
{
2018-07-22 19:34:13 +02:00
ABILITY_HEAL_MON_STATUS :
2018-07-22 18:40:18 +02:00
if ( gBattleMons [ battler ] . status1 & ( STATUS1_POISON | STATUS1_TOXIC_POISON ) )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
if ( gBattleMons [ battler ] . status1 & STATUS1_SLEEP )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
if ( gBattleMons [ battler ] . status1 & STATUS1_PARALYSIS )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
if ( gBattleMons [ battler ] . status1 & STATUS1_BURN )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
if ( gBattleMons [ battler ] . status1 & STATUS1_FREEZE )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
2018-07-22 19:34:13 +02:00
2018-07-22 18:40:18 +02:00
gBattleMons [ battler ] . status1 = 0 ;
2018-07-22 19:34:13 +02:00
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2018-07-22 18:40:18 +02:00
gBattleScripting . battler = gActiveBattler = battler ;
BattleScriptPushCursorAndCallback ( BattleScript_ShedSkinActivates ) ;
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ battler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_SPEED_BOOST :
2021-09-03 19:13:02 +02:00
if ( CompareStat ( battler , STAT_SPEED , MAX_STAT_STAGE , CMP_LESS_THAN ) & & gDisableStructs [ battler ] . isFirstTurn ! = 2 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleMons [ battler ] . statStages [ STAT_SPEED ] + + ;
2021-04-28 03:36:37 +02:00
gBattleScripting . animArg1 = 14 + STAT_SPEED ;
2018-07-22 18:40:18 +02:00
gBattleScripting . animArg2 = 0 ;
BattleScriptPushCursorAndCallback ( BattleScript_SpeedBoostActivates ) ;
gBattleScripting . battler = battler ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-04-19 15:44:44 +02:00
case ABILITY_MOODY :
if ( gDisableStructs [ battler ] . isFirstTurn ! = 2 )
2017-09-17 15:19:15 +02:00
{
2020-04-19 16:51:29 +02:00
u32 validToRaise = 0 , validToLower = 0 ;
2020-04-19 15:44:44 +02:00
u32 statsNum = ( B_MOODY_ACC_EVASION ! = GEN_8 ) ? NUM_BATTLE_STATS : NUM_STATS ;
for ( i = STAT_ATK ; i < statsNum ; i + + )
{
2021-09-03 19:13:02 +02:00
if ( CompareStat ( battler , i , MIN_STAT_STAGE , CMP_GREATER_THAN ) )
2020-04-19 15:44:44 +02:00
validToLower | = gBitTable [ i ] ;
2021-09-03 19:13:02 +02:00
if ( CompareStat ( battler , i , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2020-04-19 15:44:44 +02:00
validToRaise | = gBitTable [ i ] ;
}
if ( validToLower ! = 0 | | validToRaise ! = 0 ) // Can lower one stat, or can raise one stat
{
gBattleScripting . statChanger = gBattleScripting . savedStatChanger = 0 ; // for raising and lowering stat respectively
if ( validToRaise ! = 0 ) // Find stat to raise
{
do
{
i = ( Random ( ) % statsNum ) + STAT_ATK ;
} while ( ! ( validToRaise & gBitTable [ i ] ) ) ;
2020-04-20 19:02:03 +02:00
SET_STATCHANGER ( i , 2 , FALSE ) ;
2020-04-19 15:44:44 +02:00
validToLower & = ~ ( gBitTable [ i ] ) ; // Can't lower the same stat as raising.
}
if ( validToLower ! = 0 ) // Find stat to lower
{
do
{
i = ( Random ( ) % statsNum ) + STAT_ATK ;
} while ( ! ( validToLower & gBitTable [ i ] ) ) ;
SET_STATCHANGER2 ( gBattleScripting . savedStatChanger , i , 1 , TRUE ) ;
}
BattleScriptPushCursorAndCallback ( BattleScript_MoodyActivates ) ;
effect + + ;
}
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_TRUANT :
gDisableStructs [ gBattlerAttacker ] . truantCounter ^ = 1 ;
2017-09-17 15:19:15 +02:00
break ;
2018-07-22 21:05:12 +02:00
case ABILITY_BAD_DREAMS :
2019-12-31 16:36:53 +01:00
if ( gBattleMons [ battler ] . status1 & STATUS1_SLEEP
| | gBattleMons [ BATTLE_OPPOSITE ( battler ) ] . status1 & STATUS1_SLEEP
| | GetBattlerAbility ( battler ) = = ABILITY_COMATOSE
| | GetBattlerAbility ( BATTLE_OPPOSITE ( battler ) ) = = ABILITY_COMATOSE )
2018-07-22 21:05:12 +02:00
{
BattleScriptPushCursorAndCallback ( BattleScript_BadDreamsActivates ) ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-07-11 14:25:57 +02:00
SOLAR_POWER_HP_DROP :
2018-07-26 21:56:23 +02:00
case ABILITY_SOLAR_POWER :
2021-05-24 17:52:45 +02:00
if ( IsBattlerWeatherAffected ( battler , WEATHER_SUN_ANY ) )
2017-09-17 15:19:15 +02:00
{
2018-07-26 21:56:23 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SolarPowerActivates ) ;
gBattleMoveDamage = gBattleMons [ battler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-04-18 19:09:17 +02:00
case ABILITY_HEALER :
gBattleScripting . battler = BATTLE_PARTNER ( battler ) ;
if ( IsBattlerAlive ( gBattleScripting . battler )
& & gBattleMons [ gBattleScripting . battler ] . status1 & STATUS1_ANY
& & ( Random ( ) % 100 ) < 30 )
{
BattleScriptPushCursorAndCallback ( BattleScript_HealerActivates ) ;
effect + + ;
}
break ;
2020-04-21 20:43:47 +02:00
case ABILITY_SCHOOLING :
if ( gBattleMons [ battler ] . level < 20 )
break ;
2020-04-19 21:18:39 +02:00
case ABILITY_ZEN_MODE :
case ABILITY_SHIELDS_DOWN :
if ( ( effect = ShouldChangeFormHpBased ( battler ) ) )
BattleScriptPushCursorAndCallback ( BattleScript_AttackerFormChangeEnd3 ) ;
break ;
2020-07-16 15:40:56 +02:00
case ABILITY_POWER_CONSTRUCT :
if ( ( gBattleMons [ battler ] . species = = SPECIES_ZYGARDE | | gBattleMons [ battler ] . species = = SPECIES_ZYGARDE_10 )
& & gBattleMons [ battler ] . hp < = gBattleMons [ battler ] . maxHP / 2 )
{
gBattleStruct - > changedSpecies [ gBattlerPartyIndexes [ battler ] ] = gBattleMons [ battler ] . species ;
gBattleMons [ battler ] . species = SPECIES_ZYGARDE_COMPLETE ;
BattleScriptPushCursorAndCallback ( BattleScript_AttackerFormChangeEnd3 ) ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-12-03 03:09:35 +01:00
case ABILITY_BALL_FETCH :
if ( gBattleMons [ battler ] . item = = ITEM_NONE
2021-01-07 08:30:34 +01:00
& & gBattleResults . catchAttempts [ gLastUsedBall - ITEM_ULTRA_BALL ] > = 1
2020-12-03 03:09:35 +01:00
& & ! gHasFetchedBall )
{
gBattleScripting . battler = battler ;
BtlController_EmitSetMonData ( 0 , REQUEST_HELDITEM_BATTLE , 0 , 2 , & gLastUsedBall ) ;
MarkBattlerForControllerExec ( battler ) ;
gHasFetchedBall = TRUE ;
gLastUsedItem = gLastUsedBall ;
BattleScriptPushCursorAndCallback ( BattleScript_BallFetch ) ;
effect + + ;
}
break ;
2021-11-03 07:45:03 +01:00
case ABILITY_HUNGER_SWITCH :
if ( ! ( gBattleMons [ battler ] . status2 & STATUS2_TRANSFORMED ) )
{
if ( gBattleMons [ battler ] . species = = SPECIES_MORPEKO )
{
gBattleMons [ battler ] . species = SPECIES_MORPEKO_HANGRY ;
2021-11-04 03:40:26 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_AttackerFormChangeEnd3NoPopup ) ;
2021-11-03 07:45:03 +01:00
}
else if ( gBattleMons [ battler ] . species = = SPECIES_MORPEKO_HANGRY )
{
gBattleMons [ battler ] . species = SPECIES_MORPEKO ;
2021-11-04 03:40:26 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_AttackerFormChangeEnd3NoPopup ) ;
2021-11-03 07:45:03 +01:00
}
effect + + ;
}
break ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_MOVES_BLOCK : // 2
2021-11-23 04:56:11 +01:00
{
2021-11-24 00:09:54 +01:00
u16 moveTarget = GetBattlerMoveTargetType ( battler , move ) ;
2021-11-23 04:56:11 +01:00
if ( ( gLastUsedAbility = = ABILITY_SOUNDPROOF & & gBattleMoves [ move ] . flags & FLAG_SOUND & & ! ( moveTarget & MOVE_TARGET_USER ) )
2018-08-05 13:39:22 +02:00
| | ( gLastUsedAbility = = ABILITY_BULLETPROOF & & gBattleMoves [ move ] . flags & FLAG_BALLISTIC ) )
2018-07-22 18:40:18 +02:00
{
2018-08-02 20:24:18 +02:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_MULTIPLETURNS )
gHitMarker | = HITMARKER_NO_PPDEDUCT ;
gBattlescriptCurrInstr = BattleScript_SoundproofProtected ;
effect = 1 ;
2018-07-22 18:40:18 +02:00
}
2019-12-31 13:33:54 +01:00
else if ( ( ( ( gLastUsedAbility = = ABILITY_DAZZLING | | gLastUsedAbility = = ABILITY_QUEENLY_MAJESTY
| | ( IsBattlerAlive ( battler ^ = BIT_FLANK )
& & ( ( GetBattlerAbility ( battler ) = = ABILITY_DAZZLING ) | | GetBattlerAbility ( battler ) = = ABILITY_QUEENLY_MAJESTY ) ) )
2019-12-19 19:53:07 +01:00
) )
2019-12-31 13:33:54 +01:00
& & GetChosenMovePriority ( gBattlerAttacker ) > 0
2018-11-30 22:12:18 +01:00
& & GetBattlerSide ( gBattlerAttacker ) ! = GetBattlerSide ( battler ) )
{
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_MULTIPLETURNS )
gHitMarker | = HITMARKER_NO_PPDEDUCT ;
gBattlescriptCurrInstr = BattleScript_DazzlingProtected ;
effect = 1 ;
}
2021-10-16 16:15:15 +02:00
else if ( BlocksPrankster ( move , gBattlerAttacker , gBattlerTarget , TRUE )
& & ! ( IS_MOVE_STATUS ( move ) & & GetBattlerAbility ( gBattlerTarget ) = = ABILITY_MAGIC_BOUNCE ) )
{
2021-11-23 04:56:11 +01:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) | | ! ( moveTarget & ( MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY ) ) )
2021-10-16 16:15:15 +02:00
CancelMultiTurnMoves ( gBattlerAttacker ) ; // Don't cancel moves that can hit two targets bc one target might not be protected
gBattleScripting . battler = gBattlerAbility = gBattlerTarget ;
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster ;
effect = 1 ;
}
2018-07-22 18:40:18 +02:00
break ;
2021-11-23 04:56:11 +01:00
}
2018-07-22 18:40:18 +02:00
case ABILITYEFFECT_ABSORBING : // 3
2018-08-02 20:24:18 +02:00
if ( move ! = MOVE_NONE )
2018-07-22 18:40:18 +02:00
{
u8 statId ;
switch ( gLastUsedAbility )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
case ABILITY_VOLT_ABSORB :
if ( moveType = = TYPE_ELECTRIC )
effect = 1 ;
break ;
case ABILITY_WATER_ABSORB :
case ABILITY_DRY_SKIN :
if ( moveType = = TYPE_WATER )
effect = 1 ;
break ;
case ABILITY_MOTOR_DRIVE :
if ( moveType = = TYPE_ELECTRIC )
effect = 2 , statId = STAT_SPEED ;
break ;
case ABILITY_LIGHTNING_ROD :
if ( moveType = = TYPE_ELECTRIC )
effect = 2 , statId = STAT_SPATK ;
break ;
case ABILITY_STORM_DRAIN :
if ( moveType = = TYPE_WATER )
effect = 2 , statId = STAT_SPATK ;
break ;
case ABILITY_SAP_SIPPER :
2019-02-07 21:33:03 +01:00
if ( moveType = = TYPE_GRASS )
2018-07-22 18:40:18 +02:00
effect = 2 , statId = STAT_ATK ;
break ;
case ABILITY_FLASH_FIRE :
2020-04-23 09:01:28 +02:00
if ( moveType = = TYPE_FIRE & & ! ( ( gBattleMons [ battler ] . status1 & STATUS1_FREEZE ) & & B_FLASH_FIRE_FROZEN < = GEN_4 ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
if ( ! ( gBattleResources - > flags - > flags [ battler ] & RESOURCE_FLAG_FLASH_FIRE ) )
2017-11-26 17:15:28 +01:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_FLASH_FIRE_BOOST ;
2018-07-22 18:40:18 +02:00
if ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_FlashFireBoost ;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss ;
gBattleResources - > flags - > flags [ battler ] | = RESOURCE_FLAG_FLASH_FIRE ;
2019-06-11 10:57:02 +02:00
effect = 3 ;
2017-11-26 17:15:28 +01:00
}
2018-07-22 18:40:18 +02:00
else
2017-11-26 17:15:28 +01:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_FLASH_FIRE_NO_BOOST ;
2018-07-22 18:40:18 +02:00
if ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_FlashFireBoost ;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss ;
2017-11-26 17:15:28 +01:00
effect = 3 ;
}
}
2018-07-22 18:40:18 +02:00
break ;
}
2018-09-02 00:07:19 +02:00
2018-07-22 18:40:18 +02:00
if ( effect = = 1 ) // Drain Hp ability.
{
2018-07-31 23:09:47 +02:00
if ( BATTLER_MAX_HP ( battler ) | | gStatuses3 [ battler ] & STATUS3_HEAL_BLOCK )
2017-11-26 17:15:28 +01:00
{
2018-07-22 18:40:18 +02:00
if ( ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike ) )
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless ;
else
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss ;
}
else
{
if ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_MoveHPDrain ;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss ;
2017-10-12 17:49:24 +02:00
2018-07-22 18:40:18 +02:00
gBattleMoveDamage = gBattleMons [ battler ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
2017-09-17 15:19:15 +02:00
}
}
2018-07-22 18:40:18 +02:00
else if ( effect = = 2 ) / / Boost Stat ability ;
2017-09-17 15:19:15 +02:00
{
2021-09-03 19:13:02 +02:00
if ( ! CompareStat ( battler , statId , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
if ( ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike ) )
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless ;
else
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss ;
}
else
{
if ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_MoveStatDrain ;
else
gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss ;
SET_STATCHANGER ( statId , 1 , FALSE ) ;
gBattleMons [ battler ] . statStages [ statId ] + + ;
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , statId ) ;
2017-09-17 15:19:15 +02:00
}
}
2018-07-22 18:40:18 +02:00
}
break ;
2018-09-02 00:07:19 +02:00
case ABILITYEFFECT_MOVE_END : // Think contact abilities.
2018-07-22 18:40:18 +02:00
switch ( gLastUsedAbility )
{
2018-07-26 21:56:23 +02:00
case ABILITY_JUSTIFIED :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
& & moveType = = TYPE_DARK
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_ATK , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2018-07-26 21:56:23 +02:00
{
SET_STATCHANGER ( STAT_ATK , 1 , FALSE ) ;
BattleScriptPushCursor ( ) ;
2020-12-02 22:46:29 +01:00
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaiseOnMoveEnd ;
2018-07-26 21:56:23 +02:00
effect + + ;
}
2017-09-17 15:19:15 +02:00
break ;
2018-07-26 21:56:23 +02:00
case ABILITY_RATTLED :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
& & ( moveType = = TYPE_DARK | | moveType = = TYPE_BUG | | moveType = = TYPE_GHOST )
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_SPEED , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2018-07-26 21:56:23 +02:00
SET_STATCHANGER ( STAT_SPEED , 1 , FALSE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2020-12-02 22:46:29 +01:00
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaiseOnMoveEnd ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-04-15 09:37:12 +02:00
case ABILITY_WATER_COMPACTION :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
& & moveType = = TYPE_WATER
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_DEF , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2020-04-15 09:37:12 +02:00
SET_STATCHANGER ( STAT_DEF , 2 , FALSE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2020-12-02 22:46:29 +01:00
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaiseOnMoveEnd ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2020-04-15 09:37:12 +02:00
case ABILITY_STAMINA :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_DEF , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2020-04-15 09:37:12 +02:00
SET_STATCHANGER ( STAT_DEF , 1 , FALSE ) ;
BattleScriptPushCursor ( ) ;
2020-12-02 22:46:29 +01:00
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaiseOnMoveEnd ;
2020-04-15 09:37:12 +02:00
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2020-04-12 12:41:26 +02:00
case ABILITY_BERSERK :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
// Had more than half of hp before, now has less
& & gBattleStruct - > hpBefore [ battler ] > gBattleMons [ battler ] . maxHP / 2
& & gBattleMons [ battler ] . hp < gBattleMons [ battler ] . maxHP / 2
& & ( gMultiHitCounter = = 0 | | gMultiHitCounter = = 1 )
2020-11-13 07:30:00 +01:00
& & ! ( TestSheerForceFlag ( gBattlerAttacker , gCurrentMove ) )
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_SPATK , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2020-04-12 12:41:26 +02:00
SET_STATCHANGER ( STAT_SPATK , 1 , FALSE ) ;
BattleScriptPushCursor ( ) ;
2020-12-02 22:46:29 +01:00
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaiseOnMoveEnd ;
2020-04-12 12:41:26 +02:00
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2020-07-15 17:21:12 +02:00
case ABILITY_EMERGENCY_EXIT :
case ABILITY_WIMP_OUT :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
// Had more than half of hp before, now has less
& & gBattleStruct - > hpBefore [ battler ] > gBattleMons [ battler ] . maxHP / 2
& & gBattleMons [ battler ] . hp < gBattleMons [ battler ] . maxHP / 2
& & ( gMultiHitCounter = = 0 | | gMultiHitCounter = = 1 )
2020-11-13 07:30:00 +01:00
& & ! ( TestSheerForceFlag ( gBattlerAttacker , gCurrentMove ) )
2020-07-15 17:21:12 +02:00
& & ( CanBattlerSwitch ( battler ) | | ! ( gBattleTypeFlags & BATTLE_TYPE_TRAINER ) )
2021-06-08 03:31:12 +02:00
& & ! ( gBattleTypeFlags & BATTLE_TYPE_ARENA )
2021-06-08 16:34:23 +02:00
& & CountUsablePartyMons ( battler ) > 0 )
2017-09-17 15:19:15 +02:00
{
2020-07-15 17:21:12 +02:00
gBattleResources - > flags - > flags [ battler ] | = RESOURCE_FLAG_EMERGENCY_EXIT ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2018-07-26 21:56:23 +02:00
case ABILITY_WEAK_ARMOR :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
2020-10-16 01:15:44 +02:00
& & IS_MOVE_PHYSICAL ( gCurrentMove )
2021-09-03 19:13:02 +02:00
& & ( CompareStat ( battler , STAT_SPEED , MAX_STAT_STAGE , CMP_LESS_THAN ) // Don't activate if speed cannot be raised
| | CompareStat ( battler , STAT_DEF , MIN_STAT_STAGE , CMP_GREATER_THAN ) ) ) // Don't activate if defense cannot be lowered
2017-09-17 15:19:15 +02:00
{
2021-09-14 21:38:16 +02:00
if ( gBattleMoves [ gCurrentMove ] . effect = = EFFECT_HIT_ESCAPE & & CanBattlerSwitch ( gBattlerAttacker ) )
2021-09-23 04:29:00 +02:00
gProtectStructs [ battler ] . disableEjectPack = TRUE ; // Set flag for target
2021-09-16 23:10:41 +02:00
2018-07-26 21:56:23 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_WeakArmorActivates ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2018-07-26 21:56:23 +02:00
case ABILITY_CURSED_BODY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & gDisableStructs [ gBattlerAttacker ] . disabledMove = = MOVE_NONE
& & IsBattlerAlive ( gBattlerAttacker )
2019-04-01 11:42:37 +02:00
& & ! IsAbilityOnSide ( gBattlerAttacker , ABILITY_AROMA_VEIL )
2019-03-30 11:58:19 +01:00
& & gBattleMons [ gBattlerAttacker ] . pp [ gChosenMovePos ] ! = 0
2018-07-26 21:56:23 +02:00
& & ( Random ( ) % 3 ) = = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-26 21:56:23 +02:00
gDisableStructs [ gBattlerAttacker ] . disabledMove = gChosenMove ;
2018-10-14 20:51:34 +02:00
gDisableStructs [ gBattlerAttacker ] . disableTimer = 4 ;
2018-07-26 21:56:23 +02:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , gChosenMove ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_CursedBodyActivates ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2018-07-26 21:56:23 +02:00
case ABILITY_MUMMY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & IsBattlerAlive ( gBattlerAttacker )
2020-12-14 20:27:48 +01:00
& & TARGET_TURN_DAMAGED
2021-06-05 22:47:05 +02:00
& & ( IsMoveMakingContact ( move , gBattlerAttacker ) ) )
2017-09-17 15:19:15 +02:00
{
2018-07-26 21:56:23 +02:00
switch ( gBattleMons [ gBattlerAttacker ] . ability )
2017-09-17 15:19:15 +02:00
{
2018-07-26 21:56:23 +02:00
case ABILITY_MUMMY :
case ABILITY_BATTLE_BOND :
case ABILITY_COMATOSE :
case ABILITY_DISGUISE :
case ABILITY_MULTITYPE :
case ABILITY_POWER_CONSTRUCT :
case ABILITY_RKS_SYSTEM :
case ABILITY_SCHOOLING :
case ABILITY_SHIELDS_DOWN :
case ABILITY_STANCE_CHANGE :
break ;
default :
gLastUsedAbility = gBattleMons [ gBattlerAttacker ] . ability = ABILITY_MUMMY ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_MummyActivates ;
effect + + ;
break ;
2017-09-17 15:19:15 +02:00
}
}
break ;
2021-10-12 16:32:51 +02:00
case ABILITY_WANDERING_SPIRIT :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & IsBattlerAlive ( gBattlerAttacker )
& & TARGET_TURN_DAMAGED
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT ) )
{
switch ( gBattleMons [ gBattlerAttacker ] . ability )
{
case ABILITY_DISGUISE :
case ABILITY_FLOWER_GIFT :
case ABILITY_GULP_MISSILE :
2021-10-30 17:18:50 +02:00
case ABILITY_HUNGER_SWITCH :
2021-10-12 16:32:51 +02:00
case ABILITY_ICE_FACE :
case ABILITY_ILLUSION :
case ABILITY_IMPOSTER :
case ABILITY_RECEIVER :
case ABILITY_RKS_SYSTEM :
case ABILITY_SCHOOLING :
case ABILITY_STANCE_CHANGE :
case ABILITY_WONDER_GUARD :
case ABILITY_ZEN_MODE :
break ;
default :
gLastUsedAbility = gBattleMons [ gBattlerAttacker ] . ability ;
gBattleMons [ gBattlerAttacker ] . ability = gBattleMons [ gBattlerTarget ] . ability ;
gBattleMons [ gBattlerTarget ] . ability = gLastUsedAbility ;
2021-10-12 17:58:37 +02:00
RecordAbilityBattle ( gBattlerAttacker , gBattleMons [ gBattlerAttacker ] . ability ) ;
RecordAbilityBattle ( gBattlerTarget , gBattleMons [ gBattlerTarget ] . ability ) ;
2021-10-12 16:32:51 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_WanderingSpiritActivates ;
effect + + ;
break ;
}
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_ANGER_POINT :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gIsCriticalHit
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_ATK , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2017-09-17 15:19:15 +02:00
{
2021-04-28 03:36:37 +02:00
SET_STATCHANGER ( STAT_ATK , MAX_STAT_STAGE - gBattleMons [ battler ] . statStages [ STAT_ATK ] , FALSE ) ;
2018-07-22 18:40:18 +02:00
BattleScriptPushCursor ( ) ;
2020-12-10 22:27:35 +01:00
gBattlescriptCurrInstr = BattleScript_TargetsStatWasMaxedOut ;
2018-07-22 18:40:18 +02:00
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_COLOR_CHANGE :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & move ! = MOVE_STRUGGLE
& & gBattleMoves [ move ] . power ! = 0
& & TARGET_TURN_DAMAGED
& & ! IS_BATTLER_OF_TYPE ( battler , moveType )
& & gBattleMons [ battler ] . hp ! = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
SET_BATTLER_TYPE ( battler , moveType ) ;
PREPARE_TYPE_BUFFER ( gBattleTextBuff1 , moveType ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_ColorChangeActivates ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2019-12-20 23:38:38 +01:00
case ABILITY_GOOEY :
case ABILITY_TANGLING_HAIR :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
2021-10-13 00:04:34 +02:00
& & ( CompareStat ( gBattlerAttacker , STAT_SPEED , MIN_STAT_STAGE , CMP_GREATER_THAN ) | | GetBattlerAbility ( gBattlerAttacker ) = = ABILITY_MIRROR_ARMOR )
2019-12-20 23:38:38 +01:00
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
2019-12-25 12:19:09 +01:00
& & IsMoveMakingContact ( move , gBattlerAttacker ) )
2017-09-17 15:19:15 +02:00
{
2021-10-13 00:04:34 +02:00
SET_STATCHANGER ( STAT_SPEED , 1 , TRUE ) ;
gBattleScripting . moveEffect = MOVE_EFFECT_SPD_MINUS_1 ;
2019-12-20 23:38:38 +01:00
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , gLastUsedAbility ) ;
BattleScriptPushCursor ( ) ;
2021-10-13 00:04:34 +02:00
gBattlescriptCurrInstr = BattleScript_GooeyActivates ;
2019-12-20 23:38:38 +01:00
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_ROUGH_SKIN :
2018-07-26 21:56:23 +02:00
case ABILITY_IRON_BARBS :
2018-07-22 18:40:18 +02:00
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
2019-12-25 12:19:09 +01:00
& & IsMoveMakingContact ( move , gBattlerAttacker ) )
2017-09-17 15:19:15 +02:00
{
2021-10-25 01:07:22 +02:00
# if B_ROUGH_SKIN_DMG >= GEN_4
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 8 ;
# else
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 16 ;
# endif
2018-07-22 18:40:18 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2019-03-15 13:54:11 +01:00
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , gLastUsedAbility ) ;
2018-07-22 18:40:18 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_RoughSkinActivates ;
effect + + ;
}
break ;
2019-12-21 09:01:42 +01:00
case ABILITY_AFTERMATH :
2019-12-25 12:19:09 +01:00
if ( ! IsAbilityOnField ( ABILITY_DAMP )
& & ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
2019-12-21 09:01:42 +01:00
& & gBattleMons [ gBattlerTarget ] . hp = = 0
2020-07-26 12:32:02 +02:00
& & IsBattlerAlive ( gBattlerAttacker )
2019-12-25 12:19:09 +01:00
& & IsMoveMakingContact ( move , gBattlerAttacker ) )
2019-12-21 09:01:42 +01:00
{
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AftermathDmg ;
effect + + ;
2018-07-22 18:40:18 +02:00
}
break ;
2020-04-18 20:12:29 +02:00
case ABILITY_INNARDS_OUT :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
2020-07-26 12:32:02 +02:00
& & gBattleMons [ gBattlerTarget ] . hp = = 0
& & IsBattlerAlive ( gBattlerAttacker ) )
2020-04-18 20:12:29 +02:00
{
gBattleMoveDamage = gSpecialStatuses [ gBattlerTarget ] . dmg ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AftermathDmg ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_EFFECT_SPORE :
2019-05-23 09:47:21 +02:00
if ( ! IS_BATTLER_OF_TYPE ( gBattlerAttacker , TYPE_GRASS )
2019-03-02 22:48:55 +01:00
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_OVERCOAT
2021-10-09 04:05:01 +02:00
& & GetBattlerHoldEffect ( gBattlerAttacker , TRUE ) ! = HOLD_EFFECT_SAFETY_GOGGLES )
2019-05-23 09:47:21 +02:00
{
i = Random ( ) % 3 ;
if ( i = = 0 )
goto POISON_POINT ;
if ( i = = 1 )
goto STATIC ;
// Sleep
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
2021-01-16 19:40:02 +01:00
& & CanSleep ( gBattlerAttacker )
2020-04-19 14:24:31 +02:00
& & IsMoveMakingContact ( move , gBattlerAttacker )
2019-05-23 09:47:21 +02:00
& & ( Random ( ) % 3 ) = = 0 )
2017-09-17 15:19:15 +02:00
{
2019-05-23 09:47:21 +02:00
gBattleScripting . moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_SLEEP ;
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , gLastUsedAbility ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
}
break ;
2019-05-23 09:47:21 +02:00
POISON_POINT :
2018-07-22 18:40:18 +02:00
case ABILITY_POISON_POINT :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
2021-10-30 10:12:18 +02:00
& & CanBePoisoned ( gBattlerAttacker , gBattlerTarget )
2020-04-19 14:24:31 +02:00
& & IsMoveMakingContact ( move , gBattlerAttacker )
2018-07-22 18:40:18 +02:00
& & ( Random ( ) % 3 ) = = 0 )
2017-09-17 15:19:15 +02:00
{
2019-02-14 13:17:27 +01:00
gBattleScripting . moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_POISON ;
2019-05-23 09:47:21 +02:00
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , gLastUsedAbility ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2019-03-01 13:59:08 +01:00
gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect ;
2017-09-17 15:19:15 +02:00
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
2019-05-23 09:47:21 +02:00
STATIC :
2018-07-22 18:40:18 +02:00
case ABILITY_STATIC :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
2021-01-16 19:40:02 +01:00
& & CanBeParalyzed ( gBattlerAttacker )
2020-04-19 14:24:31 +02:00
& & IsMoveMakingContact ( move , gBattlerAttacker )
2018-07-22 18:40:18 +02:00
& & ( Random ( ) % 3 ) = = 0 )
2017-09-17 15:19:15 +02:00
{
2019-02-14 13:17:27 +01:00
gBattleScripting . moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_PARALYSIS ;
2018-07-22 18:40:18 +02:00
BattleScriptPushCursor ( ) ;
2019-03-01 13:59:08 +01:00
gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect ;
2018-07-22 18:40:18 +02:00
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_FLAME_BODY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
2021-06-05 22:47:05 +02:00
& & ( IsMoveMakingContact ( move , gBattlerAttacker ) )
2018-07-22 18:40:18 +02:00
& & TARGET_TURN_DAMAGED
2021-01-16 19:40:02 +01:00
& & CanBeBurned ( gBattlerAttacker )
2018-07-22 18:40:18 +02:00
& & ( Random ( ) % 3 ) = = 0 )
{
2019-02-14 13:17:27 +01:00
gBattleScripting . moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN ;
2018-07-22 18:40:18 +02:00
BattleScriptPushCursor ( ) ;
2019-03-01 13:59:08 +01:00
gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect ;
2018-07-22 18:40:18 +02:00
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_CUTE_CHARM :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
2021-06-05 22:47:05 +02:00
& & ( IsMoveMakingContact ( move , gBattlerAttacker ) )
2018-07-22 18:40:18 +02:00
& & TARGET_TURN_DAMAGED
& & gBattleMons [ gBattlerTarget ] . hp ! = 0
& & ( Random ( ) % 3 ) = = 0
2019-04-01 11:42:37 +02:00
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_OBLIVIOUS
& & ! IsAbilityOnSide ( gBattlerAttacker , ABILITY_AROMA_VEIL )
2018-07-22 18:40:18 +02:00
& & GetGenderFromSpeciesAndPersonality ( speciesAtk , pidAtk ) ! = GetGenderFromSpeciesAndPersonality ( speciesDef , pidDef )
& & ! ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_INFATUATION )
& & GetGenderFromSpeciesAndPersonality ( speciesAtk , pidAtk ) ! = MON_GENDERLESS
& & GetGenderFromSpeciesAndPersonality ( speciesDef , pidDef ) ! = MON_GENDERLESS )
{
gBattleMons [ gBattlerAttacker ] . status2 | = STATUS2_INFATUATED_WITH ( gBattlerTarget ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_CuteCharmActivates ;
effect + + ;
}
break ;
2019-08-08 13:06:55 +02:00
case ABILITY_ILLUSION :
2020-06-28 19:45:48 +02:00
if ( gBattleStruct - > illusion [ gBattlerTarget ] . on & & ! gBattleStruct - > illusion [ gBattlerTarget ] . broken & & TARGET_TURN_DAMAGED )
2019-08-08 13:06:55 +02:00
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_IllusionOff ;
effect + + ;
}
break ;
2020-12-03 02:53:00 +01:00
case ABILITY_COTTON_DOWN :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
2020-12-07 19:03:52 +01:00
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
2020-12-03 02:53:00 +01:00
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED )
{
2020-12-07 19:03:52 +01:00
gEffectBattler = gBattlerTarget ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_CottonDownActivates ;
effect + + ;
2020-12-03 02:53:00 +01:00
}
break ;
2020-12-10 22:27:35 +01:00
case ABILITY_STEAM_ENGINE :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
2021-09-03 19:13:02 +02:00
& & CompareStat ( battler , STAT_SPEED , MAX_STAT_STAGE , CMP_LESS_THAN )
2020-12-10 22:27:35 +01:00
& & ( moveType = = TYPE_FIRE | | moveType = = TYPE_WATER ) )
{
2021-01-07 20:19:56 +01:00
SET_STATCHANGER ( STAT_SPEED , 6 , FALSE ) ;
2020-12-10 22:27:35 +01:00
BattleScriptPushCursor ( ) ;
2021-01-07 20:19:56 +01:00
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaiseOnMoveEnd ;
2020-12-10 22:27:35 +01:00
effect + + ;
}
break ;
2020-12-11 20:41:53 +01:00
case ABILITY_SAND_SPIT :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
2021-10-12 03:29:08 +02:00
& & ! ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SANDSTORM_ANY ) )
2020-12-11 20:41:53 +01:00
{
2021-10-12 03:29:08 +02:00
if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_PRIMAL_ANY )
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BlockedByPrimalWeatherRet ;
effect + + ;
}
else if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_SANDSTORM , TRUE ) )
{
gBattleScripting . battler = gActiveBattler = battler ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_SandSpitActivates ;
effect + + ;
}
2020-12-11 20:41:53 +01:00
}
break ;
2020-12-11 23:00:30 +01:00
case ABILITY_PERISH_BODY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
2021-06-05 22:47:05 +02:00
& & ( IsMoveMakingContact ( move , gBattlerAttacker ) )
2020-12-11 23:00:30 +01:00
& & ! ( gStatuses3 [ gBattlerAttacker ] & STATUS3_PERISH_SONG ) )
{
if ( ! ( gStatuses3 [ battler ] & STATUS3_PERISH_SONG ) )
{
gStatuses3 [ battler ] | = STATUS3_PERISH_SONG ;
gDisableStructs [ battler ] . perishSongTimer = 3 ;
gDisableStructs [ battler ] . perishSongTimerStartValue = 3 ;
}
gStatuses3 [ gBattlerAttacker ] | = STATUS3_PERISH_SONG ;
gDisableStructs [ gBattlerAttacker ] . perishSongTimer = 3 ;
gDisableStructs [ gBattlerAttacker ] . perishSongTimerStartValue = 3 ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_PerishBodyActivates ;
effect + + ;
}
break ;
2021-01-12 18:58:24 +01:00
case ABILITY_GULP_MISSILE :
2020-04-19 14:43:54 +02:00
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
2021-01-12 18:58:24 +01:00
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
2021-09-29 11:13:56 +02:00
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler ) )
2020-04-19 14:43:54 +02:00
{
2021-09-28 02:31:42 +02:00
if ( gBattleMons [ gBattlerTarget ] . species = = SPECIES_CRAMORANT_GORGING )
2021-09-27 00:59:56 +02:00
{
2021-09-28 02:31:42 +02:00
gBattleStruct - > changedSpecies [ gBattlerPartyIndexes [ gBattlerTarget ] ] = gBattleMons [ gBattlerTarget ] . species ;
gBattleMons [ gBattlerTarget ] . species = SPECIES_CRAMORANT ;
if ( GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_MAGIC_GUARD )
{
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
}
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_GulpMissileGorging ;
effect + + ;
2021-09-27 00:59:56 +02:00
}
2021-09-28 02:31:42 +02:00
else if ( gBattleMons [ gBattlerTarget ] . species = = SPECIES_CRAMORANT_GULPING )
2021-09-27 00:59:56 +02:00
{
2021-09-28 02:31:42 +02:00
gBattleStruct - > changedSpecies [ gBattlerPartyIndexes [ gBattlerTarget ] ] = gBattleMons [ gBattlerTarget ] . species ;
gBattleMons [ gBattlerTarget ] . species = SPECIES_CRAMORANT ;
if ( GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_MAGIC_GUARD )
{
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
}
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_GulpMissileGulping ;
effect + + ;
2021-09-27 00:59:56 +02:00
}
2021-01-12 18:58:24 +01:00
}
break ;
2018-07-22 18:40:18 +02:00
}
break ;
2020-04-19 14:43:54 +02:00
case ABILITYEFFECT_MOVE_END_ATTACKER : // Same as above, but for attacker
switch ( gLastUsedAbility )
{
case ABILITY_POISON_TOUCH :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerTarget ] . hp ! = 0
2021-11-03 02:49:14 +01:00
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
2021-10-30 10:12:18 +02:00
& & CanBePoisoned ( gBattlerAttacker , gBattlerTarget )
2020-04-19 14:43:54 +02:00
& & IsMoveMakingContact ( move , gBattlerAttacker )
2021-10-30 10:12:18 +02:00
& & TARGET_TURN_DAMAGED // Need to actually hit the target
2020-04-19 14:43:54 +02:00
& & ( Random ( ) % 3 ) = = 0 )
{
gBattleScripting . moveEffect = MOVE_EFFECT_POISON ;
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , gLastUsedAbility ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
2021-04-04 02:55:49 +02:00
case ABILITY_STENCH :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerTarget ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & ( Random ( ) % 10 ) = = 0
& & ! IS_MOVE_STATUS ( move )
& & ! sMovesNotAffectedByStench [ gCurrentMove ] )
{
gBattleScripting . moveEffect = MOVE_EFFECT_FLINCH ;
BattleScriptPushCursor ( ) ;
SetMoveEffect ( FALSE , 0 ) ;
BattleScriptPop ( ) ;
effect + + ;
}
break ;
2021-01-12 18:58:24 +01:00
case ABILITY_GULP_MISSILE :
2021-09-29 11:13:56 +02:00
if ( ( ( gCurrentMove = = MOVE_SURF & & TARGET_TURN_DAMAGED ) | | gStatuses3 [ gBattlerAttacker ] & STATUS3_UNDERWATER )
& & ( effect = ShouldChangeFormHpBased ( gBattlerAttacker ) ) )
2021-01-12 18:58:24 +01:00
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AttackerFormChange ;
effect + + ;
}
break ;
2020-04-19 14:43:54 +02:00
}
break ;
2019-11-14 00:03:20 +01:00
case ABILITYEFFECT_MOVE_END_OTHER : // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis
switch ( GetBattlerAbility ( battler ) )
{
case ABILITY_DANCER :
if ( IsBattlerAlive ( battler )
& & ( gBattleMoves [ gCurrentMove ] . flags & FLAG_DANCE )
& & ! gSpecialStatuses [ battler ] . dancerUsedMove
& & gBattlerAttacker ! = battler )
{
// Set bit and save Dancer mon's original target
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battler ] . dancerUsedMove = TRUE ;
2019-11-14 00:03:20 +01:00
gSpecialStatuses [ battler ] . dancerOriginalTarget = * ( gBattleStruct - > moveTarget + battler ) | 0x4 ;
2020-10-19 23:01:19 +02:00
gBattleStruct - > atkCancellerTracker = 0 ;
2019-11-14 00:03:20 +01:00
gBattlerAttacker = gBattlerAbility = battler ;
gCalledMove = gCurrentMove ;
2019-12-23 17:26:48 +01:00
2019-11-14 00:03:20 +01:00
// Set the target to the original target of the mon that first used a Dance move
gBattlerTarget = gBattleScripting . savedBattler & 0x3 ;
2019-12-23 17:26:48 +01:00
2019-11-14 00:03:20 +01:00
// Make sure that the target isn't an ally - if it is, target the original user
if ( GetBattlerSide ( gBattlerTarget ) = = GetBattlerSide ( gBattlerAttacker ) )
gBattlerTarget = ( gBattleScripting . savedBattler & 0xF0 ) > > 4 ;
gHitMarker & = ~ ( HITMARKER_ATTACKSTRING_PRINTED ) ;
BattleScriptExecute ( BattleScript_DancerActivates ) ;
effect + + ;
}
break ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITYEFFECT_IMMUNITY : // 5
for ( battler = 0 ; battler < gBattlersCount ; battler + + )
{
2021-10-31 22:19:30 +01:00
switch ( GetBattlerAbility ( battler ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
case ABILITY_IMMUNITY :
if ( gBattleMons [ battler ] . status1 & ( STATUS1_POISON | STATUS1_TOXIC_POISON | STATUS1_TOXIC_COUNTER ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_OWN_TEMPO :
if ( gBattleMons [ battler ] . status2 & STATUS2_CONFUSION )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
effect = 2 ;
}
break ;
case ABILITY_LIMBER :
if ( gBattleMons [ battler ] . status1 & STATUS1_PARALYSIS )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_INSOMNIA :
case ABILITY_VITAL_SPIRIT :
if ( gBattleMons [ battler ] . status1 & STATUS1_SLEEP )
{
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_WATER_VEIL :
2021-07-25 15:53:44 +02:00
case ABILITY_WATER_BUBBLE :
2018-07-22 18:40:18 +02:00
if ( gBattleMons [ battler ] . status1 & STATUS1_BURN )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_MAGMA_ARMOR :
if ( gBattleMons [ battler ] . status1 & STATUS1_FREEZE )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_OBLIVIOUS :
if ( gBattleMons [ battler ] . status2 & STATUS2_INFATUATION )
effect = 3 ;
2021-06-03 12:55:44 +02:00
else if ( gDisableStructs [ battler ] . tauntTimer ! = 0 )
effect = 4 ;
2018-07-22 18:40:18 +02:00
break ;
}
if ( effect )
{
switch ( effect )
{
case 1 : // status cleared
gBattleMons [ battler ] . status1 = 0 ;
2021-06-03 12:55:44 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus ;
2018-07-22 18:40:18 +02:00
break ;
case 2 : // get rid of confusion
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2021-06-03 12:55:44 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus ;
2018-07-22 18:40:18 +02:00
break ;
case 3 : // get rid of infatuation
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
2021-06-03 12:55:44 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BattlerGotOverItsInfatuation ;
break ;
case 4 : // get rid of taunt
gDisableStructs [ battler ] . tauntTimer = 0 ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BattlerShookOffTaunt ;
2017-09-17 15:19:15 +02:00
break ;
}
2018-07-22 18:40:18 +02:00
2020-03-14 12:23:51 +01:00
gBattleScripting . battler = gActiveBattler = gBattlerAbility = battler ;
2018-07-22 18:40:18 +02:00
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
return effect ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_FORECAST : // 6
for ( battler = 0 ; battler < gBattlersCount ; battler + + )
{
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( battler ) = = ABILITY_FORECAST | | GetBattlerAbility ( battler ) = = ABILITY_FLOWER_GIFT )
2017-09-17 15:19:15 +02:00
{
2019-06-15 14:46:35 +02:00
effect = TryWeatherFormChange ( battler ) ;
2018-07-22 18:40:18 +02:00
if ( effect )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
gBattleScripting . battler = battler ;
2019-08-30 12:25:21 +02:00
gBattleStruct - > formToChangeInto = effect - 1 ;
2018-07-22 18:40:18 +02:00
return effect ;
}
}
}
break ;
2019-08-30 12:25:21 +02:00
case ABILITYEFFECT_SYNCHRONIZE :
2018-07-22 18:40:18 +02:00
if ( gLastUsedAbility = = ABILITY_SYNCHRONIZE & & ( gHitMarker & HITMARKER_SYNCHRONISE_EFFECT ) )
{
gHitMarker & = ~ ( HITMARKER_SYNCHRONISE_EFFECT ) ;
2019-06-25 13:04:14 +02:00
if ( ! ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_ANY ) )
{
gBattleStruct - > synchronizeMoveEffect & = ~ ( MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN ) ;
2021-11-06 01:16:13 +01:00
# if B_SYNCHRONIZE_TOXIC < GEN_5
if ( gBattleStruct - > synchronizeMoveEffect = = MOVE_EFFECT_TOXIC )
gBattleStruct - > synchronizeMoveEffect = MOVE_EFFECT_POISON ;
# endif
2019-06-25 13:04:14 +02:00
gBattleScripting . moveEffect = gBattleStruct - > synchronizeMoveEffect + MOVE_EFFECT_AFFECTS_USER ;
gBattleScripting . battler = gBattlerAbility = gBattlerTarget ;
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , ABILITY_SYNCHRONIZE ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_SynchronizeActivates ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_ATK_SYNCHRONIZE : // 8
if ( gLastUsedAbility = = ABILITY_SYNCHRONIZE & & ( gHitMarker & HITMARKER_SYNCHRONISE_EFFECT ) )
{
gHitMarker & = ~ ( HITMARKER_SYNCHRONISE_EFFECT ) ;
2019-06-25 13:04:14 +02:00
if ( ! ( gBattleMons [ gBattlerTarget ] . status1 & STATUS1_ANY ) )
{
gBattleStruct - > synchronizeMoveEffect & = ~ ( MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN ) ;
if ( gBattleStruct - > synchronizeMoveEffect = = MOVE_EFFECT_TOXIC )
gBattleStruct - > synchronizeMoveEffect = MOVE_EFFECT_POISON ;
gBattleScripting . moveEffect = gBattleStruct - > synchronizeMoveEffect ;
gBattleScripting . battler = gBattlerAbility = gBattlerAttacker ;
PREPARE_ABILITY_BUFFER ( gBattleTextBuff1 , ABILITY_SYNCHRONIZE ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_SynchronizeActivates ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
2018-07-22 18:40:18 +02:00
}
break ;
2019-08-30 12:25:21 +02:00
case ABILITYEFFECT_INTIMIDATE1 :
case ABILITYEFFECT_INTIMIDATE2 :
2018-07-22 18:40:18 +02:00
for ( i = 0 ; i < gBattlersCount ; i + + )
{
2021-10-31 22:19:30 +01:00
if ( GetBattlerAbility ( i ) = = ABILITY_INTIMIDATE & & gBattleResources - > flags - > flags [ i ] & RESOURCE_FLAG_INTIMIDATED )
2018-07-22 18:40:18 +02:00
{
gLastUsedAbility = ABILITY_INTIMIDATE ;
2019-02-25 16:17:23 +01:00
gBattleResources - > flags - > flags [ i ] & = ~ ( RESOURCE_FLAG_INTIMIDATED ) ;
2019-08-30 12:25:21 +02:00
if ( caseID = = ABILITYEFFECT_INTIMIDATE1 )
{
BattleScriptPushCursorAndCallback ( BattleScript_IntimidateActivatesEnd3 ) ;
}
else
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_IntimidateActivates ;
}
2020-06-26 15:14:15 +02:00
battler = gBattlerAbility = gBattleStruct - > intimidateBattler = i ;
2018-07-22 18:40:18 +02:00
effect + + ;
break ;
2017-09-17 15:19:15 +02:00
}
}
2018-07-22 18:40:18 +02:00
break ;
2019-08-30 12:25:21 +02:00
case ABILITYEFFECT_TRACE1 :
case ABILITYEFFECT_TRACE2 :
2018-07-22 18:40:18 +02:00
for ( i = 0 ; i < gBattlersCount ; i + + )
{
2019-02-25 16:17:23 +01:00
if ( gBattleMons [ i ] . ability = = ABILITY_TRACE & & ( gBattleResources - > flags - > flags [ i ] & RESOURCE_FLAG_TRACED ) )
2018-07-22 18:40:18 +02:00
{
2019-08-30 12:25:21 +02:00
u8 side = ( GetBattlerPosition ( i ) ^ BIT_SIDE ) & BIT_SIDE ; // side of the opposing pokemon
u8 target1 = GetBattlerAtPosition ( side ) ;
u8 target2 = GetBattlerAtPosition ( side + BIT_FLANK ) ;
2018-07-22 18:40:18 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
2020-02-17 10:59:39 +01:00
if ( ! sAbilitiesNotTraced [ gBattleMons [ target1 ] . ability ] & & gBattleMons [ target1 ] . hp ! = 0
& & ! sAbilitiesNotTraced [ gBattleMons [ target2 ] . ability ] & & gBattleMons [ target2 ] . hp ! = 0 )
2019-08-30 12:25:21 +02:00
gActiveBattler = GetBattlerAtPosition ( ( ( Random ( ) & 1 ) * 2 ) | side ) , effect + + ;
2020-02-17 10:59:39 +01:00
else if ( ! sAbilitiesNotTraced [ gBattleMons [ target1 ] . ability ] & & gBattleMons [ target1 ] . hp ! = 0 )
2019-08-30 12:25:21 +02:00
gActiveBattler = target1 , effect + + ;
2020-02-17 10:59:39 +01:00
else if ( ! sAbilitiesNotTraced [ gBattleMons [ target2 ] . ability ] & & gBattleMons [ target2 ] . hp ! = 0 )
2019-08-30 12:25:21 +02:00
gActiveBattler = target2 , effect + + ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
else
2017-09-17 15:19:15 +02:00
{
2020-02-17 10:59:39 +01:00
if ( ! sAbilitiesNotTraced [ gBattleMons [ target1 ] . ability ] & & gBattleMons [ target1 ] . hp ! = 0 )
2019-08-30 12:25:21 +02:00
gActiveBattler = target1 , effect + + ;
2018-07-22 18:40:18 +02:00
}
2019-08-30 12:25:21 +02:00
2018-07-22 18:40:18 +02:00
if ( effect )
{
2019-08-30 12:25:21 +02:00
if ( caseID = = ABILITYEFFECT_TRACE1 )
{
BattleScriptPushCursorAndCallback ( BattleScript_TraceActivatesEnd3 ) ;
}
else
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TraceActivates ;
}
2019-02-25 16:17:23 +01:00
gBattleResources - > flags - > flags [ i ] & = ~ ( RESOURCE_FLAG_TRACED ) ;
2019-08-30 12:25:21 +02:00
gBattleStruct - > tracedAbility [ i ] = gLastUsedAbility = gBattleMons [ gActiveBattler ] . ability ;
2020-06-26 15:14:15 +02:00
battler = gBattlerAbility = gBattleScripting . battler = i ;
2017-10-12 17:49:24 +02:00
2018-07-22 18:40:18 +02:00
PREPARE_MON_NICK_WITH_PREFIX_BUFFER ( gBattleTextBuff1 , gActiveBattler , gBattlerPartyIndexes [ gActiveBattler ] )
PREPARE_ABILITY_BUFFER ( gBattleTextBuff2 , gLastUsedAbility )
2017-09-17 15:19:15 +02:00
break ;
}
}
2018-07-22 18:40:18 +02:00
}
break ;
2021-10-30 04:32:19 +02:00
case ABILITYEFFECT_NEUTRALIZINGGAS :
2021-10-31 22:19:30 +01:00
// Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards
2021-10-30 04:32:19 +02:00
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 + + ;
}
2021-11-01 20:10:51 +01:00
if ( effect )
break ;
2021-10-30 04:32:19 +02:00
}
break ;
2017-09-17 15:19:15 +02:00
}
2019-03-31 21:38:58 +02:00
if ( effect & & gLastUsedAbility ! = 0xFF )
2018-07-22 18:40:18 +02:00
RecordAbilityBattle ( battler , gLastUsedAbility ) ;
2018-09-29 13:36:33 +02:00
if ( effect & & caseID < = ABILITYEFFECT_MOVE_END )
gBattlerAbility = battler ;
2018-07-22 18:40:18 +02:00
2017-09-17 15:19:15 +02:00
return effect ;
}
2017-09-17 17:14:32 +02:00
2021-10-31 22:19:30 +01:00
bool32 IsNeutralizingGasBannedAbility ( u32 ability )
2021-10-30 04:32:19 +02:00
{
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 ;
}
}
2021-10-31 22:19:30 +01:00
bool32 IsNeutralizingGasOnField ( void )
2021-10-30 04:32:19 +02:00
{
u32 i ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
2021-11-01 18:50:57 +01:00
if ( IsBattlerAlive ( i ) & & gBattleMons [ i ] . ability = = ABILITY_NEUTRALIZING_GAS & & ! ( gStatuses3 [ i ] & STATUS3_GASTRO_ACID ) )
2021-10-30 04:32:19 +02:00
return TRUE ;
}
return FALSE ;
}
2019-03-31 21:38:58 +02:00
u32 GetBattlerAbility ( u8 battlerId )
{
if ( gStatuses3 [ battlerId ] & STATUS3_GASTRO_ACID )
return ABILITY_NONE ;
2021-10-30 04:32:19 +02:00
if ( IsNeutralizingGasOnField ( ) & & ! IsNeutralizingGasBannedAbility ( gBattleMons [ battlerId ] . ability ) )
return ABILITY_NONE ;
if ( ( ( ( gBattleMons [ gBattlerAttacker ] . ability = = ABILITY_MOLD_BREAKER
2019-03-31 21:38:58 +02:00
| | gBattleMons [ gBattlerAttacker ] . ability = = ABILITY_TERAVOLT
| | gBattleMons [ gBattlerAttacker ] . ability = = ABILITY_TURBOBLAZE )
2019-04-07 14:03:40 +02:00
& & ! ( gStatuses3 [ gBattlerAttacker ] & STATUS3_GASTRO_ACID ) )
| | gBattleMoves [ gCurrentMove ] . flags & FLAG_TARGET_ABILITY_IGNORED )
& & sAbilitiesAffectedByMoldBreaker [ gBattleMons [ battlerId ] . ability ]
& & gBattlerByTurnOrder [ gCurrentTurnActionNumber ] = = gBattlerAttacker
& & gActionsByTurnOrder [ gBattlerByTurnOrder [ gBattlerAttacker ] ] = = B_ACTION_USE_MOVE
& & gCurrentTurnActionNumber < gBattlersCount )
2019-03-31 21:38:58 +02:00
return ABILITY_NONE ;
2021-10-30 04:32:19 +02:00
return gBattleMons [ battlerId ] . ability ;
2019-03-31 21:38:58 +02:00
}
u32 IsAbilityOnSide ( u32 battlerId , u32 ability )
{
if ( IsBattlerAlive ( battlerId ) & & GetBattlerAbility ( battlerId ) = = ability )
return battlerId + 1 ;
else if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerId ) ) & & GetBattlerAbility ( BATTLE_PARTNER ( battlerId ) ) = = ability )
return BATTLE_PARTNER ( battlerId ) + 1 ;
else
return 0 ;
}
u32 IsAbilityOnOpposingSide ( u32 battlerId , u32 ability )
{
return IsAbilityOnSide ( BATTLE_OPPOSITE ( battlerId ) , ability ) ;
}
u32 IsAbilityOnField ( u32 ability )
{
u32 i ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( IsBattlerAlive ( i ) & & GetBattlerAbility ( i ) = = ability )
return i + 1 ;
}
return 0 ;
}
u32 IsAbilityOnFieldExcept ( u32 battlerId , u32 ability )
{
u32 i ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( i ! = battlerId & & IsBattlerAlive ( i ) & & GetBattlerAbility ( i ) = = ability )
return i + 1 ;
}
return 0 ;
}
2020-02-08 14:20:02 +01:00
u32 IsAbilityPreventingEscape ( u32 battlerId )
{
u32 id ;
2021-10-03 00:01:11 +02:00
# if B_GHOSTS_ESCAPE >= GEN_6
if ( IS_BATTLER_OF_TYPE ( battlerId , TYPE_GHOST ) )
return 0 ;
# endif
# if B_SHADOW_TAG_ESCAPE >= GEN_4
2021-10-31 22:19:30 +01:00
if ( ( id = IsAbilityOnOpposingSide ( battlerId , ABILITY_SHADOW_TAG ) ) & & GetBattlerAbility ( battlerId ) ! = ABILITY_SHADOW_TAG )
2021-10-03 00:01:11 +02:00
# else
if ( id = IsAbilityOnOpposingSide ( battlerId , ABILITY_SHADOW_TAG ) )
# endif
2020-02-08 14:20:02 +01:00
return id ;
if ( ( id = IsAbilityOnOpposingSide ( battlerId , ABILITY_ARENA_TRAP ) ) & & IsBattlerGrounded ( battlerId ) )
return id ;
if ( ( id = IsAbilityOnOpposingSide ( battlerId , ABILITY_MAGNET_PULL ) ) & & IS_BATTLER_OF_TYPE ( battlerId , TYPE_STEEL ) )
return id ;
return 0 ;
}
2020-04-28 11:14:20 +02:00
bool32 CanBattlerEscape ( u32 battlerId ) // no ability check
{
2021-02-07 20:05:55 +01:00
if ( GetBattlerHoldEffect ( battlerId , TRUE ) = = HOLD_EFFECT_SHED_SHELL )
return TRUE ;
else if ( ( B_GHOSTS_ESCAPE > = GEN_6 & & ! IS_BATTLER_OF_TYPE ( battlerId , TYPE_GHOST ) ) & & gBattleMons [ battlerId ] . status2 & ( STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED ) )
return FALSE ;
else if ( gStatuses3 [ battlerId ] & STATUS3_ROOTED )
return FALSE ;
else if ( gFieldStatuses & STATUS_FIELD_FAIRY_LOCK )
return FALSE ;
else
return TRUE ;
2020-04-28 11:14:20 +02:00
}
2017-11-26 13:26:58 +01:00
void BattleScriptExecute ( const u8 * BS_ptr )
2017-09-17 17:14:32 +02:00
{
gBattlescriptCurrInstr = BS_ptr ;
2018-02-06 23:09:39 +01:00
gBattleResources - > battleCallbackStack - > function [ gBattleResources - > battleCallbackStack - > size + + ] = gBattleMainFunc ;
2017-10-06 00:12:01 +02:00
gBattleMainFunc = RunBattleScriptCommands_PopCallbacksStack ;
gCurrentActionFuncId = 0 ;
2017-09-17 17:14:32 +02:00
}
2017-11-26 13:26:58 +01:00
void BattleScriptPushCursorAndCallback ( const u8 * BS_ptr )
2017-09-17 17:14:32 +02:00
{
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BS_ptr ;
2018-02-06 23:09:39 +01:00
gBattleResources - > battleCallbackStack - > function [ gBattleResources - > battleCallbackStack - > size + + ] = gBattleMainFunc ;
2017-10-06 00:12:01 +02:00
gBattleMainFunc = RunBattleScriptCommands ;
2017-09-17 17:14:32 +02:00
}
enum
{
ITEM_NO_EFFECT , // 0
ITEM_STATUS_CHANGE , // 1
ITEM_EFFECT_OTHER , // 2
ITEM_PP_CHANGE , // 3
ITEM_HP_CHANGE , // 4
ITEM_STATS_CHANGE , // 5
} ;
2021-01-16 20:05:51 +01:00
bool32 IsBattlerTerrainAffected ( u8 battlerId , u32 terrainFlag )
{
if ( ! ( gFieldStatuses & terrainFlag ) )
return FALSE ;
else if ( gStatuses3 [ battlerId ] & STATUS3_SEMI_INVULNERABLE )
return FALSE ;
return IsBattlerGrounded ( battlerId ) ;
}
2021-01-16 19:40:02 +01:00
bool32 CanSleep ( u8 battlerId )
{
u16 ability = GetBattlerAbility ( battlerId ) ;
if ( ability = = ABILITY_INSOMNIA
| | ability = = ABILITY_VITAL_SPIRIT
| | ability = = ABILITY_COMATOSE
2021-01-16 19:47:29 +01:00
| | gSideStatuses [ GetBattlerSide ( battlerId ) ] & SIDE_STATUS_SAFEGUARD
2021-01-16 19:40:02 +01:00
| | gBattleMons [ battlerId ] . status1 & STATUS1_ANY
| | IsAbilityOnSide ( battlerId , ABILITY_SWEET_VEIL )
| | IsAbilityStatusProtected ( battlerId )
2021-01-16 20:05:51 +01:00
| | IsBattlerTerrainAffected ( battlerId , STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN ) )
2021-01-16 19:40:02 +01:00
return FALSE ;
return TRUE ;
}
2021-10-30 10:12:18 +02:00
bool32 CanBePoisoned ( u8 battlerAttacker , u8 battlerTarget )
2021-01-16 19:40:02 +01:00
{
2021-10-30 10:12:18 +02:00
u16 ability = GetBattlerAbility ( battlerTarget ) ;
if ( ! ( CanPoisonType ( battlerAttacker , battlerTarget ) )
| | gSideStatuses [ GetBattlerSide ( battlerTarget ) ] & SIDE_STATUS_SAFEGUARD
| | gBattleMons [ battlerTarget ] . status1 & STATUS1_ANY
2021-01-16 19:40:02 +01:00
| | ability = = ABILITY_IMMUNITY
| | ability = = ABILITY_COMATOSE
2021-10-30 10:12:18 +02:00
| | IsAbilityOnSide ( battlerTarget , ABILITY_PASTEL_VEIL )
| | gBattleMons [ battlerTarget ] . status1 & STATUS1_ANY
| | IsAbilityStatusProtected ( battlerTarget )
| | IsBattlerTerrainAffected ( battlerTarget , STATUS_FIELD_MISTY_TERRAIN ) )
2021-01-16 19:40:02 +01:00
return FALSE ;
return TRUE ;
}
bool32 CanBeBurned ( u8 battlerId )
{
u16 ability = GetBattlerAbility ( battlerId ) ;
if ( IS_BATTLER_OF_TYPE ( battlerId , TYPE_FIRE )
2021-01-16 19:47:29 +01:00
| | gSideStatuses [ GetBattlerSide ( battlerId ) ] & SIDE_STATUS_SAFEGUARD
2021-01-16 19:40:02 +01:00
| | gBattleMons [ battlerId ] . status1 & STATUS1_ANY
| | ability = = ABILITY_WATER_VEIL
2021-09-15 22:42:23 +02:00
| | ability = = ABILITY_WATER_BUBBLE
2021-01-16 19:40:02 +01:00
| | ability = = ABILITY_COMATOSE
| | IsAbilityStatusProtected ( battlerId )
2021-01-16 20:05:51 +01:00
| | IsBattlerTerrainAffected ( battlerId , STATUS_FIELD_MISTY_TERRAIN ) )
2021-01-16 19:40:02 +01:00
return FALSE ;
return TRUE ;
}
bool32 CanBeParalyzed ( u8 battlerId )
{
u16 ability = GetBattlerAbility ( battlerId ) ;
if ( ( B_PARALYZE_ELECTRIC > = GEN_6 & & IS_BATTLER_OF_TYPE ( battlerId , TYPE_ELECTRIC ) )
2021-01-16 19:47:29 +01:00
| | gSideStatuses [ GetBattlerSide ( battlerId ) ] & SIDE_STATUS_SAFEGUARD
2021-01-16 19:40:02 +01:00
| | ability = = ABILITY_LIMBER
| | ability = = ABILITY_COMATOSE
| | gBattleMons [ battlerId ] . status1 & STATUS1_ANY
| | IsAbilityStatusProtected ( battlerId )
2021-01-16 20:05:51 +01:00
| | IsBattlerTerrainAffected ( battlerId , STATUS_FIELD_MISTY_TERRAIN ) )
2021-01-16 19:40:02 +01:00
return FALSE ;
return TRUE ;
}
bool32 CanBeFrozen ( u8 battlerId )
{
u16 ability = GetBattlerAbility ( battlerId ) ;
if ( IS_BATTLER_OF_TYPE ( battlerId , TYPE_ICE )
2021-10-06 19:32:59 +02:00
| | IsBattlerWeatherAffected ( battlerId , WEATHER_SUN_ANY )
2021-01-16 19:47:29 +01:00
| | gSideStatuses [ GetBattlerSide ( battlerId ) ] & SIDE_STATUS_SAFEGUARD
2021-01-16 19:40:02 +01:00
| | ability = = ABILITY_MAGMA_ARMOR
| | ability = = ABILITY_COMATOSE
| | gBattleMons [ battlerId ] . status1 & STATUS1_ANY
| | IsAbilityStatusProtected ( battlerId )
2021-01-16 20:05:51 +01:00
| | IsBattlerTerrainAffected ( battlerId , STATUS_FIELD_MISTY_TERRAIN ) )
2021-01-16 19:40:02 +01:00
return FALSE ;
return TRUE ;
}
2021-01-16 20:21:04 +01:00
bool32 CanBeConfused ( u8 battlerId )
{
if ( GetBattlerAbility ( gEffectBattler ) = = ABILITY_OWN_TEMPO
| | gBattleMons [ gEffectBattler ] . status2 & STATUS2_CONFUSION
| | IsBattlerTerrainAffected ( battlerId , STATUS_FIELD_MISTY_TERRAIN ) )
return FALSE ;
return TRUE ;
}
2018-07-28 16:33:01 +02:00
// second argument is 1/X of current hp compared to max hp
2021-01-06 17:37:31 +01:00
bool32 HasEnoughHpToEatBerry ( u32 battlerId , u32 hpFraction , u32 itemId )
2017-09-17 17:14:32 +02:00
{
2020-07-16 14:17:38 +02:00
bool32 isBerry = ( ItemId_GetPocket ( itemId ) = = POCKET_BERRIES ) ;
2017-09-17 17:14:32 +02:00
2020-07-08 17:22:10 +02:00
if ( gBattleMons [ battlerId ] . hp = = 0 )
return FALSE ;
2021-07-25 22:55:52 +02:00
if ( gBattleScripting . overrideBerryRequirements )
return TRUE ;
2020-07-16 14:17:38 +02:00
// Unnerve prevents consumption of opponents' berries.
2021-01-06 03:37:23 +01:00
if ( isBerry & & IsUnnerveAbilityOnOpposingSide ( battlerId ) )
2020-07-16 14:17:38 +02:00
return FALSE ;
2018-07-28 16:33:01 +02:00
if ( gBattleMons [ battlerId ] . hp < = gBattleMons [ battlerId ] . maxHP / hpFraction )
return TRUE ;
2020-07-08 17:22:10 +02:00
2020-07-16 14:17:38 +02:00
if ( hpFraction < = 4 & & GetBattlerAbility ( battlerId ) = = ABILITY_GLUTTONY & & isBerry
2020-07-08 17:22:10 +02:00
& & gBattleMons [ battlerId ] . hp < = gBattleMons [ battlerId ] . maxHP / 2 )
2017-09-17 17:14:32 +02:00
{
2018-07-28 16:33:01 +02:00
RecordAbilityBattle ( battlerId , ABILITY_GLUTTONY ) ;
return TRUE ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
return FALSE ;
}
2021-01-06 06:13:32 +01:00
static u8 HealConfuseBerry ( u32 battlerId , u32 itemId , u8 flavorId , bool32 end2 )
2020-06-29 18:04:13 +02:00
{
if ( HasEnoughHpToEatBerry ( battlerId , 2 , itemId ) )
2017-09-17 17:14:32 +02:00
{
2020-06-29 18:04:13 +02:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , flavorId ) ;
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / GetBattlerHoldEffectParam ( battlerId ) ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
2021-06-10 12:55:05 +02:00
2021-01-06 06:13:32 +01:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
{
gBattleMoveDamage * = 2 ;
gBattlerAbility = battlerId ;
}
2021-10-10 13:46:31 +02:00
gBattleScripting . battler = battlerId ;
2021-01-06 06:13:32 +01:00
if ( end2 )
{
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , flavorId ) < 0 )
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
else
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItemEnd2 ) ;
}
2020-06-29 18:04:13 +02:00
else
2021-01-06 06:13:32 +01:00
{
BattleScriptPushCursor ( ) ;
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , flavorId ) < 0 )
gBattlescriptCurrInstr = BattleScript_BerryConfuseHealRet ;
else
gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet ;
}
2020-06-29 18:04:13 +02:00
return ITEM_HP_CHANGE ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
return 0 ;
}
2021-01-06 06:13:32 +01:00
static u8 StatRaiseBerry ( u32 battlerId , u32 itemId , u32 statId , bool32 end2 )
2020-06-29 18:04:13 +02:00
{
2021-09-03 19:13:02 +02:00
if ( CompareStat ( battlerId , statId , MAX_STAT_STAGE , CMP_LESS_THAN ) & & HasEnoughHpToEatBerry ( battlerId , GetBattlerHoldEffectParam ( battlerId ) , itemId ) )
2017-09-17 17:14:32 +02:00
{
2021-09-14 21:07:15 +02:00
BufferStatChange ( battlerId , statId , STRINGID_STATROSE ) ;
2020-06-29 18:04:13 +02:00
gEffectBattler = battlerId ;
2021-01-06 06:13:32 +01:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
SET_STATCHANGER ( statId , 2 , FALSE ) ;
else
SET_STATCHANGER ( statId , 1 , FALSE ) ;
2021-06-10 12:55:05 +02:00
2021-04-28 03:36:37 +02:00
gBattleScripting . animArg1 = 14 + statId ;
2020-06-29 18:04:13 +02:00
gBattleScripting . animArg2 = 0 ;
2021-06-10 12:55:05 +02:00
2021-01-06 06:13:32 +01:00
if ( end2 )
{
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
}
else
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet ;
}
2020-06-29 18:04:13 +02:00
return ITEM_STATS_CHANGE ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
return 0 ;
}
2021-01-06 06:13:32 +01:00
static u8 RandomStatRaiseBerry ( u32 battlerId , u32 itemId , bool32 end2 )
2020-06-29 18:04:13 +02:00
{
s32 i ;
2021-09-14 21:07:15 +02:00
u16 stringId ;
2017-09-17 17:14:32 +02:00
2020-06-29 18:04:13 +02:00
for ( i = 0 ; i < 5 ; i + + )
2017-09-17 17:14:32 +02:00
{
2021-09-03 19:13:02 +02:00
if ( CompareStat ( battlerId , STAT_ATK + i , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2020-06-29 18:04:13 +02:00
break ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
if ( i ! = 5 & & HasEnoughHpToEatBerry ( battlerId , GetBattlerHoldEffectParam ( battlerId ) , itemId ) )
2017-09-17 17:14:32 +02:00
{
2020-06-29 18:04:13 +02:00
do
{
i = Random ( ) % 5 ;
2021-09-03 19:13:02 +02:00
} while ( ! CompareStat ( battlerId , STAT_ATK + i , MAX_STAT_STAGE , CMP_LESS_THAN ) ) ;
2020-06-29 18:04:13 +02:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , i + 1 ) ;
2021-09-14 21:07:15 +02:00
stringId = ( GetBattlerAbility ( battlerId ) = = ABILITY_CONTRARY ) ? STRINGID_STATFELL : STRINGID_STATROSE ;
2020-06-29 18:04:13 +02:00
gBattleTextBuff2 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff2 [ 1 ] = B_BUFF_STRING ;
gBattleTextBuff2 [ 2 ] = STRINGID_STATSHARPLY ;
gBattleTextBuff2 [ 3 ] = STRINGID_STATSHARPLY > > 8 ;
gBattleTextBuff2 [ 4 ] = B_BUFF_STRING ;
2021-09-14 21:07:15 +02:00
gBattleTextBuff2 [ 5 ] = stringId ;
gBattleTextBuff2 [ 6 ] = stringId > > 8 ;
2020-06-29 18:04:13 +02:00
gBattleTextBuff2 [ 7 ] = EOS ;
gEffectBattler = battlerId ;
2021-01-06 06:13:32 +01:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
SET_STATCHANGER ( i + 1 , 4 , FALSE ) ;
else
SET_STATCHANGER ( i + 1 , 2 , FALSE ) ;
2021-06-10 12:55:05 +02:00
2020-06-29 18:04:13 +02:00
gBattleScripting . animArg1 = 0x21 + i + 6 ;
gBattleScripting . animArg2 = 0 ;
2021-01-06 06:13:32 +01:00
if ( end2 )
{
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
}
else
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet ;
}
2021-09-16 23:10:41 +02:00
2020-06-29 18:04:13 +02:00
return ITEM_STATS_CHANGE ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
return 0 ;
2018-07-28 16:33:01 +02:00
}
2017-09-17 17:14:32 +02:00
2021-01-06 18:47:07 +01:00
static u8 TrySetMicleBerry ( u32 battlerId , u32 itemId , bool32 end2 )
{
if ( HasEnoughHpToEatBerry ( battlerId , 4 , itemId ) )
{
2021-09-23 04:29:26 +02:00
gProtectStructs [ battlerId ] . usedMicleBerry = TRUE ; // battler's next attack has increased accuracy
2021-06-10 12:55:05 +02:00
2021-01-06 18:47:07 +01:00
if ( end2 )
{
BattleScriptExecute ( BattleScript_MicleBerryActivateEnd2 ) ;
}
else
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_MicleBerryActivateRet ;
}
return ITEM_EFFECT_OTHER ;
}
return 0 ;
}
2021-01-06 21:07:18 +01:00
static u8 DamagedStatBoostBerryEffect ( u8 battlerId , u8 statId , u8 split )
{
if ( IsBattlerAlive ( battlerId )
2021-03-03 17:14:14 +01:00
& & TARGET_TURN_DAMAGED
2021-09-03 19:13:02 +02:00
& & CompareStat ( battlerId , statId , MAX_STAT_STAGE , CMP_LESS_THAN )
2021-03-03 17:14:14 +01:00
& & ! DoesSubstituteBlockMove ( gBattlerAttacker , battlerId , gCurrentMove )
& & GetBattleMoveSplit ( gCurrentMove ) = = split )
2021-01-06 21:07:18 +01:00
{
2021-09-14 21:07:15 +02:00
BufferStatChange ( battlerId , statId , STRINGID_STATROSE ) ;
2021-01-06 21:07:18 +01:00
gEffectBattler = battlerId ;
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
SET_STATCHANGER ( statId , 2 , FALSE ) ;
else
SET_STATCHANGER ( statId , 1 , FALSE ) ;
2021-06-10 12:55:05 +02:00
2021-04-28 03:36:37 +02:00
gBattleScripting . animArg1 = 14 + statId ;
2021-01-06 21:07:18 +01:00
gBattleScripting . animArg2 = 0 ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet ;
2020-06-29 18:04:13 +02:00
return ITEM_STATS_CHANGE ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
return 0 ;
2018-07-28 16:33:01 +02:00
}
2017-09-17 17:14:32 +02:00
2021-01-07 04:22:05 +01:00
u8 TryHandleSeed ( u8 battler , u32 terrainFlag , u8 statId , u16 itemId , bool32 execute )
{
2021-09-03 19:13:02 +02:00
if ( gFieldStatuses & terrainFlag & & CompareStat ( battler , statId , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2021-01-07 04:22:05 +01:00
{
2021-09-14 21:07:15 +02:00
BufferStatChange ( battler , statId , STRINGID_STATROSE ) ;
2021-09-02 21:33:42 +02:00
gLastUsedItem = itemId ; // For surge abilities
2021-09-14 18:50:36 +02:00
gEffectBattler = gBattleScripting . battler = battler ;
2021-01-07 04:22:05 +01:00
SET_STATCHANGER ( statId , 1 , FALSE ) ;
gBattleScripting . animArg1 = 0xE + statId ;
gBattleScripting . animArg2 = 0 ;
if ( execute )
{
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
}
else
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet ;
}
return ITEM_STATS_CHANGE ;
}
return 0 ;
}
2020-06-29 18:56:19 +02:00
static u8 ItemHealHp ( u32 battlerId , u32 itemId , bool32 end2 , bool32 percentHeal )
{
2021-10-14 00:39:24 +02:00
if ( HasEnoughHpToEatBerry ( battlerId , 2 , itemId )
& & ! ( gBattleScripting . overrideBerryRequirements & & gBattleMons [ battlerId ] . hp = = gBattleMons [ battlerId ] . maxHP ) )
2017-09-17 17:14:32 +02:00
{
2020-06-29 18:56:19 +02:00
if ( percentHeal )
gBattleMoveDamage = ( gBattleMons [ battlerId ] . maxHP * GetBattlerHoldEffectParam ( battlerId ) / 100 ) * - 1 ;
else
gBattleMoveDamage = GetBattlerHoldEffectParam ( battlerId ) * - 1 ;
2021-06-10 12:55:05 +02:00
2021-01-06 05:15:21 +01:00
// check ripen
if ( ItemId_GetPocket ( itemId ) = = POCKET_BERRIES & & GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
gBattleMoveDamage * = 2 ;
2021-06-10 12:55:05 +02:00
2021-01-06 05:15:21 +01:00
gBattlerAbility = battlerId ; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here
2020-06-29 18:56:19 +02:00
if ( end2 )
2017-09-17 17:14:32 +02:00
{
2020-06-29 18:56:19 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItemEnd2 ) ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:56:19 +02:00
else
2017-09-17 17:14:32 +02:00
{
2020-06-29 18:56:19 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet ;
}
return ITEM_HP_CHANGE ;
}
return 0 ;
}
2017-09-17 17:14:32 +02:00
2020-07-16 14:17:38 +02:00
static bool32 UnnerveOn ( u32 battlerId , u32 itemId )
{
2021-01-06 03:37:23 +01:00
if ( ItemId_GetPocket ( itemId ) = = POCKET_BERRIES & & IsUnnerveAbilityOnOpposingSide ( battlerId ) )
2020-07-16 14:17:38 +02:00
return TRUE ;
return FALSE ;
}
2017-11-26 11:55:17 +01:00
2021-01-16 02:11:55 +01:00
static bool32 GetMentalHerbEffect ( u8 battlerId )
{
bool32 ret = FALSE ;
2021-09-04 14:40:43 +02:00
2021-03-29 16:02:21 +02:00
// Check infatuation
2021-01-16 02:11:55 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_INFATUATION )
{
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
2021-09-15 20:51:24 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_MENTALHERBCURE_INFATUATION ; // STRINGID_TARGETGOTOVERINFATUATION
2021-01-16 02:11:55 +01:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
ret = TRUE ;
}
2021-01-16 02:28:10 +01:00
# if B_MENTAL_HERB >= GEN_5
2021-03-29 16:02:41 +02:00
// Check taunt
2021-09-04 14:40:43 +02:00
if ( gDisableStructs [ battlerId ] . tauntTimer ! = 0 )
2021-01-16 02:28:10 +01:00
{
2021-09-04 14:40:43 +02:00
gDisableStructs [ battlerId ] . tauntTimer = gDisableStructs [ battlerId ] . tauntTimer2 = 0 ;
2021-09-15 20:51:24 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_MENTALHERBCURE_TAUNT ;
2021-01-16 02:28:10 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_TAUNT ) ;
ret = TRUE ;
}
2021-03-29 16:02:51 +02:00
// Check encore
2021-09-04 14:40:43 +02:00
if ( gDisableStructs [ battlerId ] . encoreTimer ! = 0 )
2021-01-16 02:28:10 +01:00
{
2021-09-04 14:40:43 +02:00
gDisableStructs [ battlerId ] . encoredMove = 0 ;
gDisableStructs [ battlerId ] . encoreTimerStartValue = gDisableStructs [ battlerId ] . encoreTimer = 0 ;
2021-09-15 20:51:24 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_MENTALHERBCURE_ENCORE ; // STRINGID_PKMNENCOREENDED
2021-01-16 02:28:10 +01:00
ret = TRUE ;
}
2021-03-29 16:02:56 +02:00
// Check torment
2021-01-16 02:28:10 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_TORMENT )
{
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_TORMENT ) ;
2021-09-15 20:51:24 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_MENTALHERBCURE_TORMENT ;
2021-01-16 02:28:10 +01:00
ret = TRUE ;
}
2021-03-29 16:03:00 +02:00
// Check heal block
2021-01-16 02:28:10 +01:00
if ( gStatuses3 [ battlerId ] & STATUS3_HEAL_BLOCK )
{
2021-09-15 18:56:58 +02:00
gStatuses3 [ battlerId ] & = ~ ( STATUS3_HEAL_BLOCK ) ;
2021-09-15 20:51:24 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_MENTALHERBCURE_HEALBLOCK ;
2021-01-16 02:28:10 +01:00
ret = TRUE ;
}
2021-03-29 16:03:05 +02:00
// Check disable
2021-09-04 14:40:43 +02:00
if ( gDisableStructs [ battlerId ] . disableTimer ! = 0 )
2021-01-16 02:28:10 +01:00
{
2021-09-04 14:40:43 +02:00
gDisableStructs [ battlerId ] . disableTimer = gDisableStructs [ battlerId ] . disableTimerStartValue = 0 ;
gDisableStructs [ battlerId ] . disabledMove = 0 ;
2021-09-15 20:51:24 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_MENTALHERBCURE_DISABLE ;
2021-01-16 02:28:10 +01:00
ret = TRUE ;
}
# endif
2021-01-16 02:11:55 +01:00
return ret ;
}
2018-07-28 16:33:01 +02:00
u8 ItemBattleEffects ( u8 caseID , u8 battlerId , bool8 moveTurn )
{
2019-05-09 20:31:58 +02:00
int i = 0 , moveType ;
2018-07-28 16:33:01 +02:00
u8 effect = ITEM_NO_EFFECT ;
u8 changedPP = 0 ;
u8 battlerHoldEffect , atkHoldEffect ;
2020-06-29 18:04:13 +02:00
u8 atkHoldEffectParam ;
2018-07-28 16:33:01 +02:00
u16 atkItem ;
2017-11-26 11:55:17 +01:00
2018-07-28 16:33:01 +02:00
gLastUsedItem = gBattleMons [ battlerId ] . item ;
battlerHoldEffect = GetBattlerHoldEffect ( battlerId , TRUE ) ;
atkItem = gBattleMons [ gBattlerAttacker ] . item ;
atkHoldEffect = GetBattlerHoldEffect ( gBattlerAttacker , TRUE ) ;
atkHoldEffectParam = GetBattlerHoldEffectParam ( gBattlerAttacker ) ;
2017-09-17 17:14:32 +02:00
switch ( caseID )
{
2017-10-06 00:12:01 +02:00
case ITEMEFFECT_ON_SWITCH_IN :
2019-05-20 12:20:49 +02:00
if ( ! gSpecialStatuses [ battlerId ] . switchInItemDone )
2017-09-17 17:14:32 +02:00
{
2019-05-20 12:20:49 +02:00
switch ( battlerHoldEffect )
2017-09-17 17:14:32 +02:00
{
2019-05-20 12:20:49 +02:00
case HOLD_EFFECT_DOUBLE_PRIZE :
2021-09-02 06:15:58 +02:00
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER & & ! gBattleStruct - > moneyMultiplierItem )
2021-09-06 10:56:02 +02:00
{
2019-05-20 12:20:49 +02:00
gBattleStruct - > moneyMultiplier * = 2 ;
2021-09-02 06:15:58 +02:00
gBattleStruct - > moneyMultiplierItem = 1 ;
2021-09-06 10:56:02 +02:00
}
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_RESTORE_STATS :
2018-11-18 20:00:36 +01:00
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
2017-09-17 17:14:32 +02:00
{
2020-08-05 02:33:05 +02:00
if ( gBattleMons [ battlerId ] . statStages [ i ] < DEFAULT_STAT_STAGE )
2017-09-17 17:14:32 +02:00
{
2020-08-05 02:33:05 +02:00
gBattleMons [ battlerId ] . statStages [ i ] = DEFAULT_STAT_STAGE ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
}
if ( effect )
{
2018-02-08 11:17:41 +01:00
gBattleScripting . battler = battlerId ;
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = battlerId ;
2018-02-08 11:17:41 +01:00
gActiveBattler = gBattlerAttacker = battlerId ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_WhiteHerbEnd2 ) ;
2017-09-17 17:14:32 +02:00
}
break ;
case HOLD_EFFECT_CONFUSE_SPICY :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SPICY , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_DRY :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_DRY , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_SWEET :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SWEET , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_BITTER :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_BITTER , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_SOUR :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SOUR , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_ATTACK_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_ATK , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_DEFENSE_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_DEF , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_SPEED_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPEED , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_SP_ATTACK_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPATK , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_SP_DEFENSE_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPDEF , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CRITICAL_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & ! ( gBattleMons [ battlerId ] . status2 & STATUS2_FOCUS_ENERGY ) & & HasEnoughHpToEatBerry ( battlerId , GetBattlerHoldEffectParam ( battlerId ) , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 | = STATUS2_FOCUS_ENERGY ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryFocusEnergyEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_RANDOM_STAT_UP :
2020-06-29 18:04:13 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
2021-01-06 06:13:32 +01:00
effect = RandomStatRaiseBerry ( battlerId , gLastUsedItem , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CURE_PAR :
2020-07-16 14:17:38 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_PARALYSIS ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCurePrlzEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_PSN :
2020-07-16 14:17:38 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCurePsnEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_BRN :
2020-07-16 14:17:38 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & gBattleMons [ battlerId ] . status1 & STATUS1_BURN & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_BURN ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureBrnEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_FRZ :
2020-07-16 14:17:38 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_FREEZE ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureFrzEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_SLP :
2020-07-16 14:17:38 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & gBattleMons [ battlerId ] . status1 & STATUS1_SLEEP & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_SLEEP ) ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureSlpEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_STATUS :
2020-07-16 14:17:38 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 & & ( gBattleMons [ battlerId ] . status1 & STATUS1_ANY | | gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION ) & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
i = 0 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_SLEEP )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-17 17:14:32 +02:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
i + + ;
}
if ( ! ( i > 1 ) )
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CURED_PROBLEM ;
2017-09-17 17:14:32 +02:00
else
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_NORMALIZED_STATUS ;
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 = 0 ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureChosenStatusEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
2020-06-29 18:04:13 +02:00
case HOLD_EFFECT_RESTORE_HP :
2020-06-29 18:56:19 +02:00
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = ItemHealHp ( battlerId , gLastUsedItem , TRUE , FALSE ) ;
break ;
case HOLD_EFFECT_RESTORE_PCT_HP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = ItemHealHp ( battlerId , gLastUsedItem , TRUE , TRUE ) ;
2020-06-29 18:04:13 +02:00
break ;
2019-05-20 12:20:49 +02:00
case HOLD_EFFECT_AIR_BALLOON :
effect = ITEM_EFFECT_OTHER ;
2018-02-08 11:17:41 +01:00
gBattleScripting . battler = battlerId ;
2019-05-20 12:20:49 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_AirBaloonMsgIn ) ;
RecordItemEffectBattle ( battlerId , HOLD_EFFECT_AIR_BALLOON ) ;
2017-09-17 17:14:32 +02:00
break ;
2021-01-07 02:00:14 +01:00
case HOLD_EFFECT_ROOM_SERVICE :
2021-09-14 18:50:36 +02:00
if ( TryRoomService ( battlerId ) )
2021-01-07 02:00:14 +01:00
{
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
effect = ITEM_STATS_CHANGE ;
}
2021-09-03 17:16:16 +02:00
break ;
2021-01-07 04:22:05 +01:00
case HOLD_EFFECT_SEEDS :
switch ( GetBattlerHoldEffectParam ( battlerId ) )
{
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN :
effect = TryHandleSeed ( battlerId , STATUS_FIELD_ELECTRIC_TERRAIN , STAT_DEF , gLastUsedItem , TRUE ) ;
break ;
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN :
effect = TryHandleSeed ( battlerId , STATUS_FIELD_GRASSY_TERRAIN , STAT_DEF , gLastUsedItem , TRUE ) ;
break ;
case HOLD_EFFECT_PARAM_MISTY_TERRAIN :
effect = TryHandleSeed ( battlerId , STATUS_FIELD_MISTY_TERRAIN , STAT_SPDEF , gLastUsedItem , TRUE ) ;
break ;
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN :
effect = TryHandleSeed ( battlerId , STATUS_FIELD_PSYCHIC_TERRAIN , STAT_SPDEF , gLastUsedItem , TRUE ) ;
break ;
}
2021-01-07 02:00:14 +01:00
break ;
2021-01-08 05:11:56 +01:00
case HOLD_EFFECT_EJECT_PACK :
2021-09-23 03:15:02 +02:00
if ( gProtectStructs [ battlerId ] . statFell
2021-09-23 03:51:37 +02:00
& & gProtectStructs [ battlerId ] . disableEjectPack = = 0
2021-09-14 21:38:16 +02:00
& & ! ( gCurrentMove = = MOVE_PARTING_SHOT & & CanBattlerSwitch ( gBattlerAttacker ) ) ) // Does not activate if attacker used Parting Shot and can switch out
2021-01-08 05:11:56 +01:00
{
2021-09-23 03:15:02 +02:00
gProtectStructs [ battlerId ] . statFell = FALSE ;
2021-01-08 05:11:56 +01:00
gActiveBattler = gBattleScripting . battler = battlerId ;
effect = ITEM_STATS_CHANGE ;
if ( moveTurn )
{
2021-09-02 21:33:42 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret ;
}
else
{
BattleScriptExecute ( BattleScript_EjectPackActivate_End2 ) ;
2021-01-08 05:11:56 +01:00
}
}
break ;
2017-09-17 17:14:32 +02:00
}
2020-06-29 18:04:13 +02:00
2017-09-17 17:14:32 +02:00
if ( effect )
{
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battlerId ] . switchInItemDone = TRUE ;
2020-06-29 18:04:13 +02:00
gActiveBattler = gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting . battler = battlerId ;
2017-09-17 17:14:32 +02:00
switch ( effect )
{
case ITEM_STATUS_CHANGE :
2018-02-08 11:17:41 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ battlerId ] . status1 ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 17:14:32 +02:00
break ;
case ITEM_PP_CHANGE :
2019-01-19 22:32:25 +01:00
if ( ! ( gBattleMons [ battlerId ] . status2 & STATUS2_TRANSFORMED ) & & ! ( gDisableStructs [ battlerId ] . mimickedMoves & gBitTable [ i ] ) )
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . pp [ i ] = changedPP ;
2017-09-17 17:14:32 +02:00
break ;
}
}
}
break ;
case 1 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp )
2017-09-17 17:14:32 +02:00
{
2018-07-16 20:47:30 +02:00
switch ( battlerHoldEffect )
2017-09-17 17:14:32 +02:00
{
case HOLD_EFFECT_RESTORE_HP :
2020-06-29 18:56:19 +02:00
if ( ! moveTurn )
effect = ItemHealHp ( battlerId , gLastUsedItem , TRUE , FALSE ) ;
2017-09-17 17:14:32 +02:00
break ;
2020-06-29 18:56:19 +02:00
case HOLD_EFFECT_RESTORE_PCT_HP :
2021-01-06 06:13:32 +01:00
if ( ! moveTurn )
2020-06-29 18:56:19 +02:00
effect = ItemHealHp ( battlerId , gLastUsedItem , TRUE , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_RESTORE_PP :
if ( ! moveTurn )
{
2017-11-26 11:55:17 +01:00
struct Pokemon * mon ;
2017-09-17 17:14:32 +02:00
u8 ppBonuses ;
u16 move ;
2020-12-13 23:02:21 +01:00
mon = GetBattlerPartyData ( battlerId ) ;
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-09-17 17:14:32 +02:00
{
2017-11-26 11:55:17 +01:00
move = GetMonData ( mon , MON_DATA_MOVE1 + i ) ;
changedPP = GetMonData ( mon , MON_DATA_PP1 + i ) ;
ppBonuses = GetMonData ( mon , MON_DATA_PP_BONUSES ) ;
2017-09-17 17:14:32 +02:00
if ( move & & changedPP = = 0 )
break ;
}
2018-12-25 18:50:15 +01:00
if ( i ! = MAX_MON_MOVES )
2017-09-17 17:14:32 +02:00
{
u8 maxPP = CalculatePPWithBonus ( move , ppBonuses , i ) ;
2021-01-06 06:13:32 +01:00
u8 ppRestored = GetBattlerHoldEffectParam ( battlerId ) ;
2021-06-10 12:55:05 +02:00
2021-01-06 06:13:32 +01:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
{
ppRestored * = 2 ;
gBattlerAbility = battlerId ;
}
if ( changedPP + ppRestored > maxPP )
2017-09-17 17:14:32 +02:00
changedPP = maxPP ;
else
2021-01-06 06:13:32 +01:00
changedPP = changedPP + ppRestored ;
2017-11-26 11:55:17 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , move ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryPPHealEnd2 ) ;
2018-02-06 20:48:02 +01:00
BtlController_EmitSetMonData ( 0 , i + REQUEST_PPMOVE1_BATTLE , 0 , 1 , & changedPP ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_PP_CHANGE ;
}
}
break ;
case HOLD_EFFECT_RESTORE_STATS :
2018-11-18 20:00:36 +01:00
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
2017-09-17 17:14:32 +02:00
{
2021-04-28 03:36:37 +02:00
if ( gBattleMons [ battlerId ] . statStages [ i ] < DEFAULT_STAT_STAGE )
2017-09-17 17:14:32 +02:00
{
2021-04-28 03:36:37 +02:00
gBattleMons [ battlerId ] . statStages [ i ] = DEFAULT_STAT_STAGE ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
}
if ( effect )
{
2018-02-08 11:17:41 +01:00
gBattleScripting . battler = battlerId ;
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = battlerId ;
2018-02-08 11:17:41 +01:00
gActiveBattler = gBattlerAttacker = battlerId ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_WhiteHerbEnd2 ) ;
2017-09-17 17:14:32 +02:00
}
break ;
2019-05-09 20:31:58 +02:00
case HOLD_EFFECT_BLACK_SLUDGE :
if ( IS_BATTLER_OF_TYPE ( battlerId , TYPE_POISON ) )
2021-09-24 11:34:25 +02:00
{
2019-05-09 20:31:58 +02:00
goto LEFTOVERS ;
2021-09-24 11:34:25 +02:00
}
else if ( GetBattlerAbility ( battlerId ) ! = ABILITY_MAGIC_GUARD & & ! moveTurn )
2019-05-09 20:31:58 +02:00
{
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptExecute ( BattleScript_ItemHurtEnd2 ) ;
effect = ITEM_HP_CHANGE ;
RecordItemEffectBattle ( battlerId , battlerHoldEffect ) ;
PREPARE_ITEM_BUFFER ( gBattleTextBuff1 , gLastUsedItem ) ;
}
break ;
2017-09-17 17:14:32 +02:00
case HOLD_EFFECT_LEFTOVERS :
2019-05-09 20:31:58 +02:00
LEFTOVERS :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp < gBattleMons [ battlerId ] . maxHP & & ! moveTurn )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / 16 ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_End2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
2018-07-16 20:47:30 +02:00
RecordItemEffectBattle ( battlerId , battlerHoldEffect ) ;
2017-09-17 17:14:32 +02:00
}
break ;
case HOLD_EFFECT_CONFUSE_SPICY :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SPICY , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_DRY :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_DRY , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_SWEET :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SWEET , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_BITTER :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_BITTER , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CONFUSE_SOUR :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SOUR , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_ATTACK_UP :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_ATK , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_DEFENSE_UP :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_DEF , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_SPEED_UP :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPEED , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_SP_ATTACK_UP :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPATK , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_SP_DEFENSE_UP :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPDEF , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CRITICAL_UP :
2020-06-29 18:04:13 +02:00
if ( ! moveTurn & & ! ( gBattleMons [ battlerId ] . status2 & STATUS2_FOCUS_ENERGY ) & & HasEnoughHpToEatBerry ( battlerId , GetBattlerHoldEffectParam ( battlerId ) , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 | = STATUS2_FOCUS_ENERGY ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryFocusEnergyEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_RANDOM_STAT_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn )
2021-01-06 06:13:32 +01:00
effect = RandomStatRaiseBerry ( battlerId , gLastUsedItem , TRUE ) ;
2017-09-17 17:14:32 +02:00
break ;
case HOLD_EFFECT_CURE_PAR :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_PARALYSIS ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCurePrlzEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_PSN :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCurePsnEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_BRN :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_BURN ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureBrnEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_FRZ :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_FREEZE ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureFrzEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_SLP :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_SLEEP & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_SLEEP ) ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureSlpEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_CONFUSION :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureConfusionEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_CURE_STATUS :
2020-07-16 14:17:38 +02:00
if ( ( gBattleMons [ battlerId ] . status1 & STATUS1_ANY | | gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION ) & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
i = 0 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_SLEEP )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-17 17:14:32 +02:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
i + + ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
i + + ;
}
if ( ! ( i > 1 ) )
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CURED_PROBLEM ;
2017-09-17 17:14:32 +02:00
else
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_NORMALIZED_STATUS ;
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 = 0 ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureChosenStatusEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
2021-01-16 02:11:55 +01:00
case HOLD_EFFECT_MENTAL_HERB :
if ( GetMentalHerbEffect ( battlerId ) )
2017-09-17 17:14:32 +02:00
{
2021-01-16 02:11:55 +01:00
gBattleScripting . savedBattler = gBattlerAttacker ;
gBattlerAttacker = battlerId ;
BattleScriptExecute ( BattleScript_MentalHerbCureEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
2021-01-06 18:47:07 +01:00
case HOLD_EFFECT_MICLE_BERRY :
if ( ! moveTurn )
effect = TrySetMicleBerry ( battlerId , gLastUsedItem , TRUE ) ;
break ;
2017-09-17 17:14:32 +02:00
}
2019-05-10 11:03:33 +02:00
2017-09-17 17:14:32 +02:00
if ( effect )
{
2020-06-29 18:04:13 +02:00
gActiveBattler = gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting . battler = battlerId ;
2017-09-17 17:14:32 +02:00
switch ( effect )
{
case ITEM_STATUS_CHANGE :
2018-02-08 11:17:41 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ battlerId ] . status1 ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 17:14:32 +02:00
break ;
case ITEM_PP_CHANGE :
2019-01-19 22:32:25 +01:00
if ( ! ( gBattleMons [ battlerId ] . status2 & STATUS2_TRANSFORMED ) & & ! ( gDisableStructs [ battlerId ] . mimickedMoves & gBitTable [ i ] ) )
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . pp [ i ] = changedPP ;
2017-09-17 17:14:32 +02:00
break ;
}
}
}
break ;
2021-07-25 22:55:52 +02:00
case ITEMEFFECT_BATTLER_MOVE_END :
goto DO_ITEMEFFECT_MOVE_END ; // this hurts a bit to do, but is an easy solution
2018-09-01 20:00:13 +02:00
case ITEMEFFECT_MOVE_END :
2018-02-08 11:17:41 +01:00
for ( battlerId = 0 ; battlerId < gBattlersCount ; battlerId + + )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gLastUsedItem = gBattleMons [ battlerId ] . item ;
2018-07-28 16:33:01 +02:00
battlerHoldEffect = GetBattlerHoldEffect ( battlerId , TRUE ) ;
2021-07-25 22:55:52 +02:00
DO_ITEMEFFECT_MOVE_END :
2018-07-16 20:47:30 +02:00
switch ( battlerHoldEffect )
2017-09-17 17:14:32 +02:00
{
2021-01-06 18:47:07 +01:00
case HOLD_EFFECT_MICLE_BERRY :
if ( B_HP_BERRIES > = GEN_4 )
effect = TrySetMicleBerry ( battlerId , gLastUsedItem , FALSE ) ;
break ;
2020-06-29 18:04:13 +02:00
case HOLD_EFFECT_RESTORE_HP :
2020-06-29 18:56:19 +02:00
if ( B_HP_BERRIES > = GEN_4 )
effect = ItemHealHp ( battlerId , gLastUsedItem , FALSE , FALSE ) ;
break ;
case HOLD_EFFECT_RESTORE_PCT_HP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = ItemHealHp ( battlerId , gLastUsedItem , FALSE , TRUE ) ;
2020-06-29 18:04:13 +02:00
break ;
2021-01-06 06:13:32 +01:00
case HOLD_EFFECT_CONFUSE_SPICY :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SPICY , FALSE ) ;
break ;
case HOLD_EFFECT_CONFUSE_DRY :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_DRY , FALSE ) ;
break ;
case HOLD_EFFECT_CONFUSE_SWEET :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SWEET , FALSE ) ;
break ;
case HOLD_EFFECT_CONFUSE_BITTER :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_BITTER , FALSE ) ;
break ;
case HOLD_EFFECT_CONFUSE_SOUR :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = HealConfuseBerry ( battlerId , gLastUsedItem , FLAVOR_SOUR , FALSE ) ;
break ;
case HOLD_EFFECT_ATTACK_UP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_ATK , FALSE ) ;
break ;
case HOLD_EFFECT_DEFENSE_UP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_DEF , FALSE ) ;
break ;
case HOLD_EFFECT_SPEED_UP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPEED , FALSE ) ;
break ;
case HOLD_EFFECT_SP_ATTACK_UP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPATK , FALSE ) ;
break ;
case HOLD_EFFECT_SP_DEFENSE_UP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = StatRaiseBerry ( battlerId , gLastUsedItem , STAT_SPDEF , FALSE ) ;
break ;
case HOLD_EFFECT_RANDOM_STAT_UP :
if ( B_BERRIES_INSTANT > = GEN_4 )
effect = RandomStatRaiseBerry ( battlerId , gLastUsedItem , FALSE ) ;
break ;
2017-09-17 17:14:32 +02:00
case HOLD_EFFECT_CURE_PAR :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_PARALYSIS ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureParRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_PSN :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCurePsnRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_BRN :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_BURN ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureBrnRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_FRZ :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_FREEZE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureFrzRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_SLP :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_SLEEP & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 & = ~ ( STATUS1_SLEEP ) ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureSlpRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_CONFUSION :
2020-07-16 14:17:38 +02:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
2021-01-16 02:11:55 +01:00
case HOLD_EFFECT_MENTAL_HERB :
if ( GetMentalHerbEffect ( battlerId ) )
2017-09-17 17:14:32 +02:00
{
2021-01-16 02:11:55 +01:00
gBattleScripting . savedBattler = gBattlerAttacker ;
gBattlerAttacker = battlerId ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2021-01-16 02:11:55 +01:00
gBattlescriptCurrInstr = BattleScript_MentalHerbCureRet ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_CURE_STATUS :
2020-07-16 14:17:38 +02:00
if ( ( gBattleMons [ battlerId ] . status1 & STATUS1_ANY | | gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION ) & & ! UnnerveOn ( battlerId , gLastUsedItem ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_SLEEP )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-17 17:14:32 +02:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
}
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
2017-09-17 17:14:32 +02:00
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
}
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status1 = 0 ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CURED_PROBLEM ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_RESTORE_STATS :
2018-11-18 20:00:36 +01:00
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
2017-09-17 17:14:32 +02:00
{
2020-08-05 02:33:05 +02:00
if ( gBattleMons [ battlerId ] . statStages [ i ] < DEFAULT_STAT_STAGE )
2017-09-17 17:14:32 +02:00
{
2020-08-05 02:33:05 +02:00
gBattleMons [ battlerId ] . statStages [ i ] = DEFAULT_STAT_STAGE ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
}
if ( effect )
{
2018-02-08 11:17:41 +01:00
gBattleScripting . battler = battlerId ;
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = battlerId ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_WhiteHerbRet ;
2018-09-01 20:00:13 +02:00
return effect ;
2017-09-17 17:14:32 +02:00
}
break ;
}
2019-05-09 20:31:58 +02:00
2017-09-17 17:14:32 +02:00
if ( effect )
{
2020-06-29 18:04:13 +02:00
gActiveBattler = gPotentialItemEffectBattler = gBattleScripting . battler = battlerId ;
if ( effect = = ITEM_STATUS_CHANGE )
{
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
}
2017-09-17 17:14:32 +02:00
break ;
}
}
break ;
2021-09-03 17:05:11 +02:00
case ITEMEFFECT_KINGSROCK :
2021-09-17 01:36:06 +02:00
// Occur on each hit of a multi-strike move
2021-01-06 23:28:58 +01:00
switch ( atkHoldEffect )
2017-09-17 17:14:32 +02:00
{
2021-01-06 23:28:58 +01:00
case HOLD_EFFECT_FLINCH :
2021-11-12 13:47:24 +01:00
# if B_SERENE_GRACE_BOOST >= GEN_5
2021-11-11 23:48:15 +01:00
if ( GetBattlerAbility ( gBattlerAttacker ) = = ABILITY_SERENE_GRACE )
atkHoldEffectParam * = 2 ;
# endif
2021-09-02 21:33:42 +02:00
if ( gBattleMoveDamage ! = 0 // Need to have done damage
2021-01-06 23:28:58 +01:00
& & ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & ( Random ( ) % 100 ) < atkHoldEffectParam
2021-01-08 05:24:21 +01:00
& & gBattleMoves [ gCurrentMove ] . flags & FLAG_KINGS_ROCK_AFFECTED
2021-01-06 23:28:58 +01:00
& & gBattleMons [ gBattlerTarget ] . hp )
2017-09-17 17:14:32 +02:00
{
2021-01-06 23:28:58 +01:00
gBattleScripting . moveEffect = MOVE_EFFECT_FLINCH ;
BattleScriptPushCursor ( ) ;
SetMoveEffect ( FALSE , 0 ) ;
BattleScriptPop ( ) ;
2017-09-17 17:14:32 +02:00
}
2021-01-06 23:28:58 +01:00
break ;
2021-09-03 17:05:11 +02:00
case HOLD_EFFECT_BLUNDER_POLICY :
if ( gBattleStruct - > blunderPolicy
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
2021-09-03 19:13:02 +02:00
& & CompareStat ( gBattlerAttacker , STAT_SPEED , MAX_STAT_STAGE , CMP_LESS_THAN ) )
2021-09-03 17:05:11 +02:00
{
gBattleStruct - > blunderPolicy = FALSE ;
gLastUsedItem = atkItem ;
gBattleScripting . statChanger = SET_STATCHANGER ( STAT_SPEED , 2 , FALSE ) ;
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise ;
2017-09-17 17:14:32 +02:00
}
2021-09-03 17:05:11 +02:00
break ;
}
break ;
case ITEMEFFECT_LIFEORB_SHELLBELL :
2021-09-17 01:36:06 +02:00
// Occur after the final hit of a multi-strike move
2021-09-03 17:05:11 +02:00
switch ( atkHoldEffect )
{
2021-01-06 23:28:58 +01:00
case HOLD_EFFECT_SHELL_BELL :
2021-09-14 17:53:35 +02:00
if ( gSpecialStatuses [ gBattlerAttacker ] . damagedMons // Need to have done damage
2021-01-06 23:28:58 +01:00
& & gBattlerAttacker ! = gBattlerTarget
& & gBattleMons [ gBattlerAttacker ] . hp ! = gBattleMons [ gBattlerAttacker ] . maxHP
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0 )
2017-09-17 17:14:32 +02:00
{
2021-01-06 23:28:58 +01:00
gLastUsedItem = atkItem ;
gPotentialItemEffectBattler = gBattlerAttacker ;
gBattleScripting . battler = gBattlerAttacker ;
gBattleMoveDamage = ( gSpecialStatuses [ gBattlerTarget ] . dmg / atkHoldEffectParam ) * - 1 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = - 1 ;
gSpecialStatuses [ gBattlerTarget ] . dmg = 0 ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret ;
2021-09-17 01:36:06 +02:00
effect = ITEM_HP_CHANGE ;
2021-01-06 23:28:58 +01:00
}
break ;
2021-09-03 17:05:11 +02:00
case HOLD_EFFECT_LIFE_ORB :
if ( IsBattlerAlive ( gBattlerAttacker )
& & ! ( TestSheerForceFlag ( gBattlerAttacker , gCurrentMove ) )
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_MAGIC_GUARD
& & gSpecialStatuses [ gBattlerAttacker ] . damagedMons )
2021-01-06 23:28:58 +01:00
{
2021-09-03 17:05:11 +02:00
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 10 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2021-09-17 01:36:06 +02:00
effect = ITEM_HP_CHANGE ;
2021-01-06 23:28:58 +01:00
BattleScriptPushCursor ( ) ;
2021-09-03 17:05:11 +02:00
gBattlescriptCurrInstr = BattleScript_ItemHurtRet ;
gLastUsedItem = gBattleMons [ gBattlerAttacker ] . item ;
2017-09-17 17:14:32 +02:00
}
2021-01-06 23:28:58 +01:00
break ;
2021-09-03 17:05:11 +02:00
case HOLD_EFFECT_THROAT_SPRAY : // Does NOT need to be a damaging move
2021-09-14 17:53:35 +02:00
if ( gProtectStructs [ gBattlerAttacker ] . targetAffected
2021-01-06 23:40:20 +01:00
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
2021-09-03 17:05:11 +02:00
& & gBattleMoves [ gCurrentMove ] . flags & FLAG_SOUND
2021-09-03 19:13:02 +02:00
& & CompareStat ( gBattlerAttacker , STAT_SPATK , MAX_STAT_STAGE , CMP_LESS_THAN )
2021-09-17 01:36:06 +02:00
& & ! NoAliveMonsForEitherParty ( ) ) // Don't activate if battle will end
2021-01-06 23:40:20 +01:00
{
gLastUsedItem = atkItem ;
2021-09-03 17:05:11 +02:00
gBattleScripting . battler = gBattlerAttacker ;
gBattleScripting . statChanger = SET_STATCHANGER ( STAT_SPATK , 1 , FALSE ) ;
2021-01-06 23:40:20 +01:00
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise ;
2017-09-17 17:14:32 +02:00
}
2021-01-06 23:40:20 +01:00
break ;
2017-09-17 17:14:32 +02:00
}
break ;
2019-05-09 20:31:58 +02:00
case ITEMEFFECT_TARGET :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT ) )
2017-09-17 17:14:32 +02:00
{
2019-05-09 20:31:58 +02:00
GET_MOVE_TYPE ( gCurrentMove , moveType ) ;
switch ( battlerHoldEffect )
{
case HOLD_EFFECT_AIR_BALLOON :
if ( TARGET_TURN_DAMAGED )
{
effect = ITEM_EFFECT_OTHER ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AirBaloonMsgPop ;
}
break ;
case HOLD_EFFECT_ROCKY_HELMET :
if ( TARGET_TURN_DAMAGED
& & IsMoveMakingContact ( gCurrentMove , gBattlerAttacker )
2020-06-26 21:56:18 +02:00
& & IsBattlerAlive ( gBattlerAttacker )
2019-05-09 20:31:58 +02:00
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_MAGIC_GUARD )
{
2019-05-10 11:03:33 +02:00
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 6 ;
2019-05-09 20:31:58 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
effect = ITEM_HP_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_RockyHelmetActivates ;
PREPARE_ITEM_BUFFER ( gBattleTextBuff1 , gLastUsedItem ) ;
RecordItemEffectBattle ( battlerId , HOLD_EFFECT_ROCKY_HELMET ) ;
}
break ;
case HOLD_EFFECT_WEAKNESS_POLICY :
if ( IsBattlerAlive ( battlerId )
& & TARGET_TURN_DAMAGED
& & gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE )
{
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_WeaknessPolicy ;
}
break ;
case HOLD_EFFECT_SNOWBALL :
if ( IsBattlerAlive ( battlerId )
& & TARGET_TURN_DAMAGED
& & moveType = = TYPE_ICE )
{
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise ;
gBattleScripting . statChanger = SET_STATCHANGER ( STAT_ATK , 1 , FALSE ) ;
}
break ;
case HOLD_EFFECT_LUMINOUS_MOSS :
if ( IsBattlerAlive ( battlerId )
& & TARGET_TURN_DAMAGED
& & moveType = = TYPE_WATER )
{
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise ;
gBattleScripting . statChanger = SET_STATCHANGER ( STAT_SPDEF , 1 , FALSE ) ;
}
break ;
case HOLD_EFFECT_CELL_BATTERY :
if ( IsBattlerAlive ( battlerId )
& & TARGET_TURN_DAMAGED
& & moveType = = TYPE_ELECTRIC )
{
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise ;
gBattleScripting . statChanger = SET_STATCHANGER ( STAT_ATK , 1 , FALSE ) ;
}
break ;
case HOLD_EFFECT_ABSORB_BULB :
if ( IsBattlerAlive ( battlerId )
& & TARGET_TURN_DAMAGED
& & moveType = = TYPE_WATER )
{
effect = ITEM_STATS_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise ;
gBattleScripting . statChanger = SET_STATCHANGER ( STAT_SPATK , 1 , FALSE ) ;
}
break ;
2021-01-06 21:07:18 +01:00
case HOLD_EFFECT_JABOCA_BERRY : // consume and damage attacker if used physical move
2021-01-06 19:15:56 +01:00
if ( IsBattlerAlive ( battlerId )
2021-03-03 17:14:20 +01:00
& & TARGET_TURN_DAMAGED
& & ! DoesSubstituteBlockMove ( gBattlerAttacker , battlerId , gCurrentMove )
2021-03-03 17:21:06 +01:00
& & IS_MOVE_PHYSICAL ( gCurrentMove )
2021-03-03 18:48:05 +01:00
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_MAGIC_GUARD )
2021-01-06 19:15:56 +01:00
{
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
gBattleMoveDamage * = 2 ;
2021-06-10 12:55:05 +02:00
2021-01-06 19:15:56 +01:00
effect = ITEM_HP_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates ;
PREPARE_ITEM_BUFFER ( gBattleTextBuff1 , gLastUsedItem ) ;
RecordItemEffectBattle ( battlerId , HOLD_EFFECT_ROCKY_HELMET ) ;
}
break ;
2021-01-06 21:07:18 +01:00
case HOLD_EFFECT_ROWAP_BERRY : // consume and damage attacker if used special move
if ( IsBattlerAlive ( battlerId )
2021-03-03 17:14:25 +01:00
& & TARGET_TURN_DAMAGED
& & ! DoesSubstituteBlockMove ( gBattlerAttacker , battlerId , gCurrentMove )
2021-03-03 17:21:06 +01:00
& & IS_MOVE_SPECIAL ( gCurrentMove )
2021-03-03 18:48:11 +01:00
& & GetBattlerAbility ( gBattlerAttacker ) ! = ABILITY_MAGIC_GUARD )
2021-01-06 21:07:18 +01:00
{
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( GetBattlerAbility ( battlerId ) = = ABILITY_RIPEN )
gBattleMoveDamage * = 2 ;
2021-06-10 12:55:05 +02:00
2021-01-06 21:07:18 +01:00
effect = ITEM_HP_CHANGE ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates ;
PREPARE_ITEM_BUFFER ( gBattleTextBuff1 , gLastUsedItem ) ;
RecordItemEffectBattle ( battlerId , HOLD_EFFECT_ROCKY_HELMET ) ;
}
break ;
case HOLD_EFFECT_KEE_BERRY : // consume and boost defense if used physical move
effect = DamagedStatBoostBerryEffect ( battlerId , STAT_DEF , SPLIT_PHYSICAL ) ;
break ;
case HOLD_EFFECT_MARANGA_BERRY : // consume and boost sp. defense if used special move
effect = DamagedStatBoostBerryEffect ( battlerId , STAT_SPDEF , SPLIT_SPECIAL ) ;
break ;
2020-12-09 18:28:18 +01:00
case HOLD_EFFECT_STICKY_BARB :
if ( TARGET_TURN_DAMAGED
& & ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT ) )
& & IsMoveMakingContact ( gCurrentMove , gBattlerAttacker )
2021-10-06 21:30:44 +02:00
& & ! DoesSubstituteBlockMove ( gBattlerAttacker , battlerId , gCurrentMove )
2020-12-09 18:28:18 +01:00
& & IsBattlerAlive ( gBattlerAttacker )
2020-12-22 16:35:11 +01:00
& & CanStealItem ( gBattlerAttacker , gBattlerTarget , gBattleMons [ gBattlerTarget ] . item )
2020-12-09 18:28:18 +01:00
& & gBattleMons [ gBattlerAttacker ] . item = = ITEM_NONE )
{
2020-12-22 16:35:11 +01:00
// No sticky hold checks.
2020-12-21 03:06:50 +01:00
gEffectBattler = battlerId ; // gEffectBattler = target
StealTargetItem ( gBattlerAttacker , gBattlerTarget ) ; // Attacker takes target's barb
2020-12-09 18:28:18 +01:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_StickyBarbTransfer ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
2019-05-09 20:31:58 +02:00
}
}
break ;
2019-05-10 11:03:33 +02:00
case ITEMEFFECT_ORBS :
switch ( battlerHoldEffect )
{
case HOLD_EFFECT_TOXIC_ORB :
if ( ! gBattleMons [ battlerId ] . status1
2020-04-21 15:59:19 +02:00
& & CanPoisonType ( battlerId , battlerId )
2021-05-04 12:55:19 +02:00
& & GetBattlerAbility ( battlerId ) ! = ABILITY_IMMUNITY
2021-05-04 13:08:48 +02:00
& & GetBattlerAbility ( battlerId ) ! = ABILITY_COMATOSE
2021-05-04 12:55:19 +02:00
& & IsBattlerAlive )
2019-05-10 11:03:33 +02:00
{
effect = ITEM_STATUS_CHANGE ;
gBattleMons [ battlerId ] . status1 = STATUS1_TOXIC_POISON ;
BattleScriptExecute ( BattleScript_ToxicOrb ) ;
RecordItemEffectBattle ( battlerId , battlerHoldEffect ) ;
}
break ;
case HOLD_EFFECT_FLAME_ORB :
if ( ! gBattleMons [ battlerId ] . status1
& & ! IS_BATTLER_OF_TYPE ( battlerId , TYPE_FIRE )
2021-05-04 12:55:19 +02:00
& & GetBattlerAbility ( battlerId ) ! = ABILITY_WATER_VEIL
2021-05-04 13:08:48 +02:00
& & GetBattlerAbility ( battlerId ) ! = ABILITY_WATER_BUBBLE
& & GetBattlerAbility ( battlerId ) ! = ABILITY_COMATOSE
2021-05-04 12:55:19 +02:00
& & IsBattlerAlive )
2017-09-17 17:14:32 +02:00
{
2019-05-10 11:03:33 +02:00
effect = ITEM_STATUS_CHANGE ;
gBattleMons [ battlerId ] . status1 = STATUS1_BURN ;
BattleScriptExecute ( BattleScript_FlameOrb ) ;
RecordItemEffectBattle ( battlerId , battlerHoldEffect ) ;
}
break ;
2020-12-21 03:06:50 +01:00
case HOLD_EFFECT_STICKY_BARB : // Not an orb per se, but similar effect, and needs to NOT activate with pickpocket
2020-12-09 18:28:18 +01:00
if ( GetBattlerAbility ( battlerId ) ! = ABILITY_MAGIC_GUARD )
{
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptExecute ( BattleScript_ItemHurtEnd2 ) ;
effect = ITEM_HP_CHANGE ;
2019-05-10 11:03:33 +02:00
RecordItemEffectBattle ( battlerId , battlerHoldEffect ) ;
2020-12-09 18:28:18 +01:00
PREPARE_ITEM_BUFFER ( gBattleTextBuff1 , gLastUsedItem ) ;
2019-05-10 11:03:33 +02:00
}
break ;
}
if ( effect = = ITEM_STATUS_CHANGE )
{
gActiveBattler = battlerId ;
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ battlerId ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
}
break ;
2017-09-17 17:14:32 +02:00
}
2019-02-01 14:17:24 +01:00
// Berry was successfully used on a Pokemon.
if ( effect & & ( gLastUsedItem > = FIRST_BERRY_INDEX & & gLastUsedItem < = LAST_BERRY_INDEX ) )
gBattleStruct - > ateBerry [ battlerId & BIT_SIDE ] | = gBitTable [ gBattlerPartyIndexes [ battlerId ] ] ;
2017-09-17 17:14:32 +02:00
return effect ;
}
2018-02-08 11:17:41 +01:00
void ClearFuryCutterDestinyBondGrudge ( u8 battlerId )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gDisableStructs [ battlerId ] . furyCutterCounter = 0 ;
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_DESTINY_BOND ) ;
gStatuses3 [ battlerId ] & = ~ ( STATUS3_GRUDGE ) ;
2017-09-17 17:14:32 +02:00
}
2017-10-06 17:06:45 +02:00
void HandleAction_RunBattleScript ( void ) // identical to RunBattleScriptCommands
2017-09-17 17:14:32 +02:00
{
2018-02-06 20:48:02 +01:00
if ( gBattleControllerExecFlags = = 0 )
2017-09-17 17:14:32 +02:00
gBattleScriptingCommandsTable [ * gBattlescriptCurrInstr ] ( ) ;
}
2019-08-26 14:55:55 +02:00
u32 SetRandomTarget ( u32 battlerId )
{
2019-12-30 13:14:20 +01:00
u32 target ;
2019-08-26 14:55:55 +02:00
static const u8 targets [ 2 ] [ 2 ] =
{
[ B_SIDE_PLAYER ] = { B_POSITION_OPPONENT_LEFT , B_POSITION_OPPONENT_RIGHT } ,
[ B_SIDE_OPPONENT ] = { B_POSITION_PLAYER_LEFT , B_POSITION_PLAYER_RIGHT } ,
} ;
2019-12-30 13:14:20 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
target = GetBattlerAtPosition ( targets [ GetBattlerSide ( battlerId ) ] [ Random ( ) % 2 ] ) ;
if ( ! IsBattlerAlive ( target ) )
target ^ = BIT_FLANK ;
}
else
{
target = GetBattlerAtPosition ( targets [ GetBattlerSide ( battlerId ) ] [ 0 ] ) ;
}
2019-08-26 14:55:55 +02:00
return target ;
}
2021-10-16 22:10:45 +02:00
u32 GetMoveTarget ( u16 move , u8 setTarget )
2017-09-17 17:14:32 +02:00
{
2018-07-01 11:15:42 +02:00
u8 targetBattler = 0 ;
2019-08-26 14:55:55 +02:00
u32 i , moveTarget , side ;
2017-09-17 17:14:32 +02:00
2018-03-01 00:59:52 +01:00
if ( setTarget )
moveTarget = setTarget - 1 ;
2017-09-17 17:14:32 +02:00
else
2021-11-24 00:09:54 +01:00
moveTarget = GetBattlerMoveTargetType ( gBattlerAttacker , move ) ;
2021-11-23 04:56:11 +01:00
2021-09-22 14:06:42 +02:00
// Special cases
if ( move = = MOVE_CURSE & & ! IS_BATTLER_OF_TYPE ( gBattlerAttacker , TYPE_GHOST ) )
moveTarget = MOVE_TARGET_USER ;
2021-11-19 08:20:16 +01:00
2017-09-17 17:14:32 +02:00
switch ( moveTarget )
{
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_SELECTED :
2018-02-06 23:09:39 +01:00
side = GetBattlerSide ( gBattlerAttacker ) ^ BIT_SIDE ;
2021-07-25 16:22:05 +02:00
if ( IsAffectedByFollowMe ( gBattlerAttacker , side , move ) )
2019-08-22 15:57:33 +02:00
{
2018-07-01 11:15:42 +02:00
targetBattler = gSideTimers [ side ] . followmeTarget ;
2019-08-22 15:57:33 +02:00
}
2017-09-17 17:14:32 +02:00
else
{
2019-08-26 14:55:55 +02:00
targetBattler = SetRandomTarget ( gBattlerAttacker ) ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoves [ move ] . type = = TYPE_ELECTRIC
2019-03-31 21:38:58 +02:00
& & IsAbilityOnOpposingSide ( gBattlerAttacker , ABILITY_LIGHTNING_ROD )
2021-10-31 22:19:30 +01:00
& & GetBattlerAbility ( targetBattler ) ! = ABILITY_LIGHTNING_ROD )
2017-09-17 17:14:32 +02:00
{
2018-07-01 11:15:42 +02:00
targetBattler ^ = BIT_FLANK ;
RecordAbilityBattle ( targetBattler , gBattleMons [ targetBattler ] . ability ) ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ targetBattler ] . lightningRodRedirected = TRUE ;
2017-09-17 17:14:32 +02:00
}
2018-07-22 19:34:13 +02:00
else if ( gBattleMoves [ move ] . type = = TYPE_WATER
2019-03-31 21:38:58 +02:00
& & IsAbilityOnOpposingSide ( gBattlerAttacker , ABILITY_STORM_DRAIN )
2021-10-31 22:19:30 +01:00
& & GetBattlerAbility ( targetBattler ) ! = ABILITY_STORM_DRAIN )
2018-07-22 19:34:13 +02:00
{
targetBattler ^ = BIT_FLANK ;
RecordAbilityBattle ( targetBattler , gBattleMons [ targetBattler ] . ability ) ;
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ targetBattler ] . stormDrainRedirected = TRUE ;
2018-07-22 19:34:13 +02:00
}
2017-09-17 17:14:32 +02:00
}
break ;
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_DEPENDS :
case MOVE_TARGET_BOTH :
case MOVE_TARGET_FOES_AND_ALLY :
case MOVE_TARGET_OPPONENTS_FIELD :
2018-07-01 11:15:42 +02:00
targetBattler = GetBattlerAtPosition ( ( GetBattlerPosition ( gBattlerAttacker ) & BIT_SIDE ) ^ BIT_SIDE ) ;
2019-08-22 15:57:33 +02:00
if ( ! IsBattlerAlive ( targetBattler ) )
2018-07-01 11:15:42 +02:00
targetBattler ^ = BIT_FLANK ;
2017-09-17 17:14:32 +02:00
break ;
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_RANDOM :
2018-02-06 23:09:39 +01:00
side = GetBattlerSide ( gBattlerAttacker ) ^ BIT_SIDE ;
2021-07-25 16:22:05 +02:00
if ( IsAffectedByFollowMe ( gBattlerAttacker , side , move ) )
2018-07-01 11:15:42 +02:00
targetBattler = gSideTimers [ side ] . followmeTarget ;
2017-09-19 21:01:12 +02:00
else if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE & & moveTarget & MOVE_TARGET_RANDOM )
2019-08-26 14:55:55 +02:00
targetBattler = SetRandomTarget ( gBattlerAttacker ) ;
2017-09-17 17:14:32 +02:00
else
2018-07-01 11:15:42 +02:00
targetBattler = GetBattlerAtPosition ( ( GetBattlerPosition ( gBattlerAttacker ) & BIT_SIDE ) ^ BIT_SIDE ) ;
2017-09-17 17:14:32 +02:00
break ;
2018-02-26 13:24:46 +01:00
case MOVE_TARGET_USER_OR_SELECTED :
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_USER :
2018-11-25 12:59:22 +01:00
default :
2018-07-01 11:15:42 +02:00
targetBattler = gBattlerAttacker ;
2017-09-17 17:14:32 +02:00
break ;
2018-11-25 12:59:22 +01:00
case MOVE_TARGET_ALLY :
if ( IsBattlerAlive ( BATTLE_PARTNER ( gBattlerAttacker ) ) )
targetBattler = BATTLE_PARTNER ( gBattlerAttacker ) ;
else
targetBattler = gBattlerAttacker ;
break ;
2017-09-17 17:14:32 +02:00
}
2018-07-01 11:15:42 +02:00
* ( gBattleStruct - > moveTarget + gBattlerAttacker ) = targetBattler ;
2017-09-17 17:14:32 +02:00
2018-07-01 11:15:42 +02:00
return targetBattler ;
2017-09-17 17:14:32 +02:00
}
2021-04-02 22:16:40 +02:00
static bool32 IsMonEventLegal ( u8 battlerId )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
if ( GetBattlerSide ( battlerId ) = = B_SIDE_OPPONENT )
2017-09-17 17:14:32 +02:00
return TRUE ;
2018-02-08 11:17:41 +01:00
if ( GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] , MON_DATA_SPECIES , NULL ) ! = SPECIES_DEOXYS
& & GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] , MON_DATA_SPECIES , NULL ) ! = SPECIES_MEW )
2017-09-17 17:14:32 +02:00
return TRUE ;
2021-03-23 07:08:19 +01:00
return GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] , MON_DATA_EVENT_LEGAL , NULL ) ;
2017-09-17 17:14:32 +02:00
}
2017-12-02 14:08:55 +01:00
u8 IsMonDisobedient ( void )
2017-09-17 17:14:32 +02:00
{
s32 rnd ;
s32 calc ;
u8 obedienceLevel = 0 ;
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) )
2017-09-17 17:14:32 +02:00
return 0 ;
2018-02-06 23:09:39 +01:00
if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_OPPONENT )
2017-09-17 17:14:32 +02:00
return 0 ;
2021-04-02 22:16:40 +02:00
if ( IsMonEventLegal ( gBattlerAttacker ) ) // only false if illegal Mew or Deoxys
2017-09-17 17:14:32 +02:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER & & GetBattlerPosition ( gBattlerAttacker ) = = 2 )
2017-09-17 17:14:32 +02:00
return 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER )
return 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
return 0 ;
2018-02-06 23:09:39 +01:00
if ( ! IsOtherTrainer ( gBattleMons [ gBattlerAttacker ] . otId , gBattleMons [ gBattlerAttacker ] . otName ) )
2017-09-17 17:14:32 +02:00
return 0 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE08_GET ) )
2017-09-17 17:14:32 +02:00
return 0 ;
obedienceLevel = 10 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE02_GET ) )
2017-09-17 17:14:32 +02:00
obedienceLevel = 30 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE04_GET ) )
2017-09-17 17:14:32 +02:00
obedienceLevel = 50 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE06_GET ) )
2017-09-17 17:14:32 +02:00
obedienceLevel = 70 ;
}
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . level < = obedienceLevel )
2017-09-17 17:14:32 +02:00
return 0 ;
rnd = ( Random ( ) & 255 ) ;
2018-02-06 23:09:39 +01:00
calc = ( gBattleMons [ gBattlerAttacker ] . level + obedienceLevel ) * rnd > > 8 ;
2017-09-17 17:14:32 +02:00
if ( calc < obedienceLevel )
return 0 ;
// is not obedient
if ( gCurrentMove = = MOVE_RAGE )
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_RAGE ) ;
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_SLEEP & & ( gCurrentMove = = MOVE_SNORE | | gCurrentMove = = MOVE_SLEEP_TALK ) )
2017-09-17 17:14:32 +02:00
{
2018-09-01 20:00:13 +02:00
gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep ;
2017-09-17 17:14:32 +02:00
return 1 ;
}
rnd = ( Random ( ) & 255 ) ;
2018-02-06 23:09:39 +01:00
calc = ( gBattleMons [ gBattlerAttacker ] . level + obedienceLevel ) * rnd > > 8 ;
2017-09-17 17:14:32 +02:00
if ( calc < obedienceLevel )
{
2018-02-06 23:09:39 +01:00
calc = CheckMoveLimitations ( gBattlerAttacker , gBitTable [ gCurrMovePos ] , 0xFF ) ;
2017-09-17 17:14:32 +02:00
if ( calc = = 0xF ) // all moves cannot be used
{
2021-04-28 03:36:37 +02:00
// Randomly select, then print a disobedient string
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
gBattleCommunication [ MULTISTRING_CHOOSER ] = Random ( ) & ( NUM_LOAF_STRINGS - 1 ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
return 1 ;
}
else // use a random move
{
do
{
2021-04-28 03:36:37 +02:00
gCurrMovePos = gChosenMovePos = Random ( ) & ( MAX_MON_MOVES - 1 ) ;
2017-09-17 17:14:32 +02:00
} while ( gBitTable [ gCurrMovePos ] & calc ) ;
2018-09-22 18:41:00 +02:00
gCalledMove = gBattleMons [ gBattlerAttacker ] . moves [ gCurrMovePos ] ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove ;
2018-09-22 18:41:00 +02:00
gBattlerTarget = GetMoveTarget ( gCalledMove , 0 ) ;
2017-09-17 17:14:32 +02:00
gHitMarker | = HITMARKER_x200000 ;
return 2 ;
}
}
else
{
2018-02-06 23:09:39 +01:00
obedienceLevel = gBattleMons [ gBattlerAttacker ] . level - obedienceLevel ;
2017-09-17 17:14:32 +02:00
calc = ( Random ( ) & 255 ) ;
2021-01-16 19:40:02 +01:00
if ( calc < obedienceLevel & & CanSleep ( gBattlerAttacker ) )
2017-09-17 17:14:32 +02:00
{
// try putting asleep
int i ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-09-17 17:14:32 +02:00
{
if ( gBattleMons [ i ] . status2 & STATUS2_UPROAR )
break ;
}
2018-02-06 02:46:59 +01:00
if ( i = = gBattlersCount )
2017-09-17 17:14:32 +02:00
{
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep ;
2017-09-17 17:14:32 +02:00
return 1 ;
}
}
calc - = obedienceLevel ;
if ( calc < obedienceLevel )
{
2019-04-02 00:14:01 +02:00
gBattleMoveDamage = CalculateMoveDamage ( MOVE_NONE , gBattlerAttacker , gBattlerAttacker , TYPE_MYSTERY , 40 , FALSE , FALSE , TRUE ) ;
2018-02-06 23:09:39 +01:00
gBattlerTarget = gBattlerAttacker ;
2018-09-01 20:00:13 +02:00
gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself ;
2017-09-17 17:14:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
return 2 ;
}
else
{
2021-04-28 03:36:37 +02:00
// Randomly select, then print a disobedient string
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
gBattleCommunication [ MULTISTRING_CHOOSER ] = Random ( ) & ( NUM_LOAF_STRINGS - 1 ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
return 1 ;
}
}
}
2018-07-14 16:41:14 +02:00
u32 GetBattlerHoldEffect ( u8 battlerId , bool32 checkNegating )
{
if ( checkNegating )
{
if ( gStatuses3 [ battlerId ] & STATUS3_EMBARGO )
return HOLD_EFFECT_NONE ;
if ( gFieldStatuses & STATUS_FIELD_MAGIC_ROOM )
return HOLD_EFFECT_NONE ;
2021-11-16 03:29:54 +01:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_KLUTZ )
2018-07-14 16:41:14 +02:00
return HOLD_EFFECT_NONE ;
}
gPotentialItemEffectBattler = battlerId ;
2020-12-23 18:04:14 +01:00
if ( B_ENABLE_DEBUG & & gBattleStruct - > debugHoldEffects [ battlerId ] ! = 0 & & gBattleMons [ battlerId ] . item )
2019-04-13 14:56:26 +02:00
return gBattleStruct - > debugHoldEffects [ battlerId ] ;
else if ( gBattleMons [ battlerId ] . item = = ITEM_ENIGMA_BERRY )
2018-07-14 16:41:14 +02:00
return gEnigmaBerries [ battlerId ] . holdEffect ;
else
return ItemId_GetHoldEffect ( gBattleMons [ battlerId ] . item ) ;
}
u32 GetBattlerHoldEffectParam ( u8 battlerId )
{
if ( gBattleMons [ battlerId ] . item = = ITEM_ENIGMA_BERRY )
return gEnigmaBerries [ battlerId ] . holdEffectParam ;
else
return ItemId_GetHoldEffectParam ( gBattleMons [ battlerId ] . item ) ;
}
bool32 IsMoveMakingContact ( u16 move , u8 battlerAtk )
{
if ( ! ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT ) )
2021-10-27 14:28:26 +02:00
{
2021-10-27 16:19:39 +02:00
if ( gBattleMoves [ move ] . effect = = EFFECT_SHELL_SIDE_ARM & & gSwapDamageCategory )
2021-06-05 22:47:05 +02:00
return TRUE ;
else
return FALSE ;
2021-10-27 14:28:26 +02:00
}
2018-07-14 16:41:14 +02:00
else if ( GetBattlerAbility ( battlerAtk ) = = ABILITY_LONG_REACH )
2021-10-27 14:28:26 +02:00
{
2018-07-14 16:41:14 +02:00
return FALSE ;
2021-10-27 14:28:26 +02:00
}
2018-07-14 16:41:14 +02:00
else if ( GetBattlerHoldEffect ( battlerAtk , TRUE ) = = HOLD_EFFECT_PROTECTIVE_PADS )
2021-10-27 14:28:26 +02:00
{
2018-07-14 16:41:14 +02:00
return FALSE ;
2021-10-27 14:28:26 +02:00
}
2020-10-19 23:01:19 +02:00
else
2021-10-27 14:28:26 +02:00
{
2020-10-19 23:01:19 +02:00
return TRUE ;
2021-10-27 14:28:26 +02:00
}
2018-07-14 16:41:14 +02:00
}
2021-11-13 13:48:08 +01:00
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 ;
}
2021-11-19 04:21:33 +01:00
// Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here.
// This means extra logic is needed to handle Shell Side Arm.
2021-11-19 22:32:00 +01:00
if ( GetBattlerAbility ( gBattlerAttacker ) = = ABILITY_UNSEEN_FIST
2021-11-19 04:21:33 +01:00
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT | | ( gBattleMoves [ move ] . effect = = EFFECT_SHELL_SIDE_ARM & & gSwapDamageCategory ) ) )
return FALSE ;
else if ( ! ( gBattleMoves [ move ] . flags & FLAG_PROTECT_AFFECTED ) )
2021-11-13 13:48:08 +01:00
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
2021-11-24 00:09:54 +01:00
& & GetBattlerMoveTargetType ( gBattlerAttacker , move ) & ( MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY ) )
2020-10-19 23:01:19 +02:00
return TRUE ;
2021-11-13 13:48:08 +01:00
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 ;
2018-07-14 16:41:14 +02:00
}
2021-11-13 13:48:08 +01:00
2018-07-14 16:41:14 +02:00
bool32 IsBattlerGrounded ( u8 battlerId )
{
if ( GetBattlerHoldEffect ( battlerId , TRUE ) = = HOLD_EFFECT_IRON_BALL )
return TRUE ;
else if ( gFieldStatuses & STATUS_FIELD_GRAVITY )
return TRUE ;
else if ( gStatuses3 [ battlerId ] & STATUS3_ROOTED )
return TRUE ;
else if ( gStatuses3 [ battlerId ] & STATUS3_SMACKED_DOWN )
return TRUE ;
else if ( gStatuses3 [ battlerId ] & STATUS3_TELEKINESIS )
return FALSE ;
2018-07-18 22:07:48 +02:00
else if ( gStatuses3 [ battlerId ] & STATUS3_MAGNET_RISE )
return FALSE ;
2019-05-09 20:31:58 +02:00
else if ( GetBattlerHoldEffect ( battlerId , TRUE ) = = HOLD_EFFECT_AIR_BALLOON )
return FALSE ;
2018-07-14 16:41:14 +02:00
else if ( GetBattlerAbility ( battlerId ) = = ABILITY_LEVITATE )
return FALSE ;
else if ( IS_BATTLER_OF_TYPE ( battlerId , TYPE_FLYING ) )
return FALSE ;
else
2020-10-19 23:01:19 +02:00
return TRUE ;
2018-07-14 16:41:14 +02:00
}
bool32 IsBattlerAlive ( u8 battlerId )
{
if ( gBattleMons [ battlerId ] . hp = = 0 )
return FALSE ;
else if ( battlerId > = gBattlersCount )
return FALSE ;
else if ( gAbsentBattlerFlags & gBitTable [ battlerId ] )
return FALSE ;
2020-10-19 23:01:19 +02:00
else
return TRUE ;
2018-07-14 16:41:14 +02:00
}
u8 GetBattleMonMoveSlot ( struct BattlePokemon * battleMon , u16 move )
{
u8 i ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( battleMon - > moves [ i ] = = move )
break ;
}
return i ;
}
u32 GetBattlerWeight ( u8 battlerId )
{
2018-09-22 17:27:51 +02:00
u32 i ;
2018-07-14 16:41:14 +02:00
u32 weight = GetPokedexHeightWeight ( SpeciesToNationalPokedexNum ( gBattleMons [ battlerId ] . species ) , 1 ) ;
u32 ability = GetBattlerAbility ( battlerId ) ;
u32 holdEffect = GetBattlerHoldEffect ( battlerId , TRUE ) ;
if ( ability = = ABILITY_HEAVY_METAL )
weight * = 2 ;
else if ( ability = = ABILITY_LIGHT_METAL )
weight / = 2 ;
if ( holdEffect = = HOLD_EFFECT_FLOAT_STONE )
weight / = 2 ;
2020-06-27 11:21:13 +02:00
for ( i = 0 ; i < gDisableStructs [ battlerId ] . autotomizeCount ; i + + )
2018-09-22 17:27:51 +02:00
{
if ( weight > 1000 )
{
weight - = 1000 ;
}
else if ( weight < = 1000 )
{
weight = 1 ;
break ;
}
}
2018-07-14 16:41:14 +02:00
if ( weight = = 0 )
weight = 1 ;
return weight ;
}
u32 CountBattlerStatIncreases ( u8 battlerId , bool32 countEvasionAcc )
{
u32 i ;
u32 count = 0 ;
2018-11-18 20:49:52 +01:00
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
2018-07-14 16:41:14 +02:00
{
if ( ( i = = STAT_ACC | | i = = STAT_EVASION ) & & ! countEvasionAcc )
continue ;
2021-04-28 03:36:37 +02:00
if ( gBattleMons [ battlerId ] . statStages [ i ] > DEFAULT_STAT_STAGE ) // Stat is increased.
count + = gBattleMons [ battlerId ] . statStages [ i ] - DEFAULT_STAT_STAGE ;
2018-07-14 16:41:14 +02:00
}
return count ;
}
u32 GetMoveTargetCount ( u16 move , u8 battlerAtk , u8 battlerDef )
{
2021-11-24 00:09:54 +01:00
switch ( GetBattlerMoveTargetType ( gBattlerAttacker , move ) )
2018-07-14 16:41:14 +02:00
{
case MOVE_TARGET_BOTH :
return IsBattlerAlive ( battlerDef )
+ IsBattlerAlive ( BATTLE_PARTNER ( battlerDef ) ) ;
case MOVE_TARGET_FOES_AND_ALLY :
return IsBattlerAlive ( battlerDef )
+ IsBattlerAlive ( BATTLE_PARTNER ( battlerDef ) )
+ IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) ;
case MOVE_TARGET_OPPONENTS_FIELD :
return 1 ;
case MOVE_TARGET_DEPENDS :
case MOVE_TARGET_SELECTED :
case MOVE_TARGET_RANDOM :
case MOVE_TARGET_USER_OR_SELECTED :
return IsBattlerAlive ( battlerDef ) ;
case MOVE_TARGET_USER :
return IsBattlerAlive ( battlerAtk ) ;
default :
return 0 ;
}
}
2018-07-14 19:29:25 +02:00
2018-07-14 22:56:03 +02:00
static void MulModifier ( u16 * modifier , u16 val )
{
* modifier = UQ_4_12_TO_INT ( ( * modifier * val ) + UQ_4_12_ROUND ) ;
}
static u32 ApplyModifier ( u16 modifier , u32 val )
{
return UQ_4_12_TO_INT ( ( modifier * val ) + UQ_4_12_ROUND ) ;
}
2019-01-05 19:02:01 +01:00
static const u8 sFlailHpScaleToPowerTable [ ] =
{
1 , 200 ,
4 , 150 ,
9 , 100 ,
16 , 80 ,
32 , 40 ,
48 , 20
} ;
// format: min. weight (hectograms), base power
static const u16 sWeightToDamageTable [ ] =
{
100 , 20 ,
250 , 40 ,
500 , 60 ,
1000 , 80 ,
2000 , 100 ,
0xFFFF , 0xFFFF
} ;
static const u8 sSpeedDiffPowerTable [ ] = { 40 , 60 , 80 , 120 , 150 } ;
2021-10-05 01:17:43 +02:00
static const u8 sHeatCrashPowerTable [ ] = { 40 , 40 , 60 , 80 , 100 , 120 } ;
2019-01-05 19:02:01 +01:00
static const u8 sTrumpCardPowerTable [ ] = { 200 , 80 , 60 , 50 , 40 } ;
2019-05-20 12:03:00 +02:00
const struct TypePower gNaturalGiftTable [ ] =
{
[ ITEM_TO_BERRY ( ITEM_CHERI_BERRY ) ] = { TYPE_FIRE , 80 } ,
[ ITEM_TO_BERRY ( ITEM_CHESTO_BERRY ) ] = { TYPE_WATER , 80 } ,
[ ITEM_TO_BERRY ( ITEM_PECHA_BERRY ) ] = { TYPE_ELECTRIC , 80 } ,
[ ITEM_TO_BERRY ( ITEM_RAWST_BERRY ) ] = { TYPE_GRASS , 80 } ,
[ ITEM_TO_BERRY ( ITEM_ASPEAR_BERRY ) ] = { TYPE_ICE , 80 } ,
[ ITEM_TO_BERRY ( ITEM_LEPPA_BERRY ) ] = { TYPE_FIGHTING , 80 } ,
[ ITEM_TO_BERRY ( ITEM_ORAN_BERRY ) ] = { TYPE_POISON , 80 } ,
[ ITEM_TO_BERRY ( ITEM_PERSIM_BERRY ) ] = { TYPE_GROUND , 80 } ,
[ ITEM_TO_BERRY ( ITEM_LUM_BERRY ) ] = { TYPE_FLYING , 80 } ,
[ ITEM_TO_BERRY ( ITEM_SITRUS_BERRY ) ] = { TYPE_PSYCHIC , 80 } ,
[ ITEM_TO_BERRY ( ITEM_FIGY_BERRY ) ] = { TYPE_BUG , 80 } ,
[ ITEM_TO_BERRY ( ITEM_WIKI_BERRY ) ] = { TYPE_ROCK , 80 } ,
[ ITEM_TO_BERRY ( ITEM_MAGO_BERRY ) ] = { TYPE_GHOST , 80 } ,
[ ITEM_TO_BERRY ( ITEM_AGUAV_BERRY ) ] = { TYPE_DRAGON , 80 } ,
[ ITEM_TO_BERRY ( ITEM_IAPAPA_BERRY ) ] = { TYPE_DARK , 80 } ,
[ ITEM_TO_BERRY ( ITEM_RAZZ_BERRY ) ] = { TYPE_STEEL , 80 } ,
[ ITEM_TO_BERRY ( ITEM_OCCA_BERRY ) ] = { TYPE_FIRE , 80 } ,
[ ITEM_TO_BERRY ( ITEM_PASSHO_BERRY ) ] = { TYPE_WATER , 80 } ,
[ ITEM_TO_BERRY ( ITEM_WACAN_BERRY ) ] = { TYPE_ELECTRIC , 80 } ,
[ ITEM_TO_BERRY ( ITEM_RINDO_BERRY ) ] = { TYPE_GRASS , 80 } ,
[ ITEM_TO_BERRY ( ITEM_YACHE_BERRY ) ] = { TYPE_ICE , 80 } ,
[ ITEM_TO_BERRY ( ITEM_CHOPLE_BERRY ) ] = { TYPE_FIGHTING , 80 } ,
[ ITEM_TO_BERRY ( ITEM_KEBIA_BERRY ) ] = { TYPE_POISON , 80 } ,
[ ITEM_TO_BERRY ( ITEM_SHUCA_BERRY ) ] = { TYPE_GROUND , 80 } ,
[ ITEM_TO_BERRY ( ITEM_COBA_BERRY ) ] = { TYPE_FLYING , 80 } ,
[ ITEM_TO_BERRY ( ITEM_PAYAPA_BERRY ) ] = { TYPE_PSYCHIC , 80 } ,
[ ITEM_TO_BERRY ( ITEM_TANGA_BERRY ) ] = { TYPE_BUG , 80 } ,
[ ITEM_TO_BERRY ( ITEM_CHARTI_BERRY ) ] = { TYPE_ROCK , 80 } ,
[ ITEM_TO_BERRY ( ITEM_KASIB_BERRY ) ] = { TYPE_GHOST , 80 } ,
[ ITEM_TO_BERRY ( ITEM_HABAN_BERRY ) ] = { TYPE_DRAGON , 80 } ,
[ ITEM_TO_BERRY ( ITEM_COLBUR_BERRY ) ] = { TYPE_DARK , 80 } ,
[ ITEM_TO_BERRY ( ITEM_BABIRI_BERRY ) ] = { TYPE_STEEL , 80 } ,
[ ITEM_TO_BERRY ( ITEM_CHILAN_BERRY ) ] = { TYPE_NORMAL , 80 } ,
[ ITEM_TO_BERRY ( ITEM_ROSELI_BERRY ) ] = { TYPE_FAIRY , 80 } ,
[ ITEM_TO_BERRY ( ITEM_BLUK_BERRY ) ] = { TYPE_FIRE , 90 } ,
[ ITEM_TO_BERRY ( ITEM_NANAB_BERRY ) ] = { TYPE_WATER , 90 } ,
[ ITEM_TO_BERRY ( ITEM_WEPEAR_BERRY ) ] = { TYPE_ELECTRIC , 90 } ,
[ ITEM_TO_BERRY ( ITEM_PINAP_BERRY ) ] = { TYPE_GRASS , 90 } ,
[ ITEM_TO_BERRY ( ITEM_POMEG_BERRY ) ] = { TYPE_ICE , 90 } ,
[ ITEM_TO_BERRY ( ITEM_KELPSY_BERRY ) ] = { TYPE_FIGHTING , 90 } ,
[ ITEM_TO_BERRY ( ITEM_QUALOT_BERRY ) ] = { TYPE_POISON , 90 } ,
[ ITEM_TO_BERRY ( ITEM_HONDEW_BERRY ) ] = { TYPE_GROUND , 90 } ,
[ ITEM_TO_BERRY ( ITEM_GREPA_BERRY ) ] = { TYPE_FLYING , 90 } ,
[ ITEM_TO_BERRY ( ITEM_TAMATO_BERRY ) ] = { TYPE_PSYCHIC , 90 } ,
[ ITEM_TO_BERRY ( ITEM_CORNN_BERRY ) ] = { TYPE_BUG , 90 } ,
[ ITEM_TO_BERRY ( ITEM_MAGOST_BERRY ) ] = { TYPE_ROCK , 90 } ,
[ ITEM_TO_BERRY ( ITEM_RABUTA_BERRY ) ] = { TYPE_GHOST , 90 } ,
[ ITEM_TO_BERRY ( ITEM_NOMEL_BERRY ) ] = { TYPE_DRAGON , 90 } ,
[ ITEM_TO_BERRY ( ITEM_SPELON_BERRY ) ] = { TYPE_DARK , 90 } ,
[ ITEM_TO_BERRY ( ITEM_PAMTRE_BERRY ) ] = { TYPE_STEEL , 90 } ,
[ ITEM_TO_BERRY ( ITEM_WATMEL_BERRY ) ] = { TYPE_FIRE , 100 } ,
[ ITEM_TO_BERRY ( ITEM_DURIN_BERRY ) ] = { TYPE_WATER , 100 } ,
[ ITEM_TO_BERRY ( ITEM_BELUE_BERRY ) ] = { TYPE_ELECTRIC , 100 } ,
[ ITEM_TO_BERRY ( ITEM_LIECHI_BERRY ) ] = { TYPE_GRASS , 100 } ,
[ ITEM_TO_BERRY ( ITEM_GANLON_BERRY ) ] = { TYPE_ICE , 100 } ,
[ ITEM_TO_BERRY ( ITEM_SALAC_BERRY ) ] = { TYPE_FIGHTING , 100 } ,
[ ITEM_TO_BERRY ( ITEM_PETAYA_BERRY ) ] = { TYPE_POISON , 100 } ,
[ ITEM_TO_BERRY ( ITEM_APICOT_BERRY ) ] = { TYPE_GROUND , 100 } ,
[ ITEM_TO_BERRY ( ITEM_LANSAT_BERRY ) ] = { TYPE_FLYING , 100 } ,
[ ITEM_TO_BERRY ( ITEM_STARF_BERRY ) ] = { TYPE_PSYCHIC , 100 } ,
[ ITEM_TO_BERRY ( ITEM_ENIGMA_BERRY ) ] = { TYPE_BUG , 100 } ,
[ ITEM_TO_BERRY ( ITEM_MICLE_BERRY ) ] = { TYPE_ROCK , 100 } ,
[ ITEM_TO_BERRY ( ITEM_CUSTAP_BERRY ) ] = { TYPE_GHOST , 100 } ,
[ ITEM_TO_BERRY ( ITEM_JABOCA_BERRY ) ] = { TYPE_DRAGON , 100 } ,
[ ITEM_TO_BERRY ( ITEM_ROWAP_BERRY ) ] = { TYPE_DARK , 100 } ,
[ ITEM_TO_BERRY ( ITEM_KEE_BERRY ) ] = { TYPE_FAIRY , 100 } ,
[ ITEM_TO_BERRY ( ITEM_MARANGA_BERRY ) ] = { TYPE_DARK , 100 } ,
} ;
2018-07-14 22:56:03 +02:00
static u16 CalcMoveBasePower ( u16 move , u8 battlerAtk , u8 battlerDef )
{
u32 i ;
u16 basePower = gBattleMoves [ move ] . power ;
u32 weight , hpFraction , speed ;
switch ( gBattleMoves [ move ] . effect )
{
case EFFECT_PLEDGE :
// todo
break ;
case EFFECT_FLING :
2019-12-23 18:25:26 +01:00
// todo: program Fling + Unburden interaction
2018-07-14 22:56:03 +02:00
break ;
case EFFECT_ERUPTION :
basePower = gBattleMons [ battlerAtk ] . hp * basePower / gBattleMons [ battlerAtk ] . maxHP ;
break ;
case EFFECT_FLAIL :
hpFraction = GetScaledHPFraction ( gBattleMons [ battlerAtk ] . hp , gBattleMons [ battlerAtk ] . maxHP , 48 ) ;
for ( i = 0 ; i < sizeof ( sFlailHpScaleToPowerTable ) ; i + = 2 )
{
if ( hpFraction < = sFlailHpScaleToPowerTable [ i ] )
break ;
}
basePower = sFlailHpScaleToPowerTable [ i + 1 ] ;
break ;
case EFFECT_RETURN :
basePower = 10 * ( gBattleMons [ battlerAtk ] . friendship ) / 25 ;
break ;
case EFFECT_FRUSTRATION :
basePower = 10 * ( 255 - gBattleMons [ battlerAtk ] . friendship ) / 25 ;
break ;
case EFFECT_FURY_CUTTER :
for ( i = 1 ; i < gDisableStructs [ battlerAtk ] . furyCutterCounter ; i + + )
basePower * = 2 ;
break ;
case EFFECT_ROLLOUT :
2018-10-14 20:51:34 +02:00
for ( i = 1 ; i < ( 5 - gDisableStructs [ battlerAtk ] . rolloutTimer ) ; i + + )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
if ( gBattleMons [ battlerAtk ] . status2 & STATUS2_DEFENSE_CURL )
basePower * = 2 ;
break ;
case EFFECT_MAGNITUDE :
basePower = gBattleStruct - > magnitudeBasePower ;
break ;
case EFFECT_PRESENT :
basePower = gBattleStruct - > presentBasePower ;
break ;
case EFFECT_TRIPLE_KICK :
basePower + = gBattleScripting . tripleKickPower ;
break ;
case EFFECT_SPIT_UP :
basePower = 100 * gDisableStructs [ battlerAtk ] . stockpileCounter ;
break ;
case EFFECT_REVENGE :
if ( ( gProtectStructs [ battlerAtk ] . physicalDmg
& & gProtectStructs [ battlerAtk ] . physicalBattlerId = = battlerDef )
| | ( gProtectStructs [ battlerAtk ] . specialDmg
& & gProtectStructs [ battlerAtk ] . specialBattlerId = = battlerDef ) )
basePower * = 2 ;
break ;
case EFFECT_WEATHER_BALL :
if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_ANY )
basePower * = 2 ;
break ;
case EFFECT_PURSUIT :
2019-02-24 09:55:21 +01:00
if ( gActionsByTurnOrder [ GetBattlerTurnOrderNum ( gBattlerTarget ) ] = = B_ACTION_SWITCH )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
break ;
case EFFECT_NATURAL_GIFT :
2019-05-20 12:03:00 +02:00
basePower = gNaturalGiftTable [ ITEM_TO_BERRY ( gBattleMons [ battlerAtk ] . item ) ] . power ;
2018-07-14 22:56:03 +02:00
break ;
case EFFECT_WAKE_UP_SLAP :
2019-12-31 16:36:53 +01:00
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP | | GetBattlerAbility ( battlerDef ) = = ABILITY_COMATOSE )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
break ;
case EFFECT_SMELLINGSALT :
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_PARALYSIS )
basePower * = 2 ;
break ;
case EFFECT_WRING_OUT :
basePower = 120 * gBattleMons [ battlerDef ] . hp / gBattleMons [ battlerDef ] . maxHP ;
break ;
case EFFECT_HEX :
2019-12-31 16:36:53 +01:00
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_ANY | | GetBattlerAbility ( battlerDef ) = = ABILITY_COMATOSE )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
break ;
case EFFECT_ASSURANCE :
2021-09-23 04:29:00 +02:00
if ( gProtectStructs [ battlerDef ] . physicalDmg ! = 0 | | gProtectStructs [ battlerDef ] . specialDmg ! = 0 | | gProtectStructs [ battlerDef ] . confusionSelfDmg )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
break ;
case EFFECT_TRUMP_CARD :
i = GetBattleMonMoveSlot ( & gBattleMons [ battlerAtk ] , move ) ;
if ( i ! = 4 )
{
2019-01-05 19:02:01 +01:00
if ( gBattleMons [ battlerAtk ] . pp [ i ] > = ARRAY_COUNT ( sTrumpCardPowerTable ) )
basePower = sTrumpCardPowerTable [ ARRAY_COUNT ( sTrumpCardPowerTable ) - 1 ] ;
else
2021-10-05 00:40:36 +02:00
basePower = sTrumpCardPowerTable [ gBattleMons [ battlerAtk ] . pp [ i ] ] ;
2018-07-14 22:56:03 +02:00
}
break ;
case EFFECT_ACROBATICS :
2020-04-27 10:58:35 +02:00
if ( gBattleMons [ battlerAtk ] . item = = ITEM_NONE
// Edge case, because removal of items happens after damage calculation.
| | ( gSpecialStatuses [ battlerAtk ] . gemBoost & & GetBattlerHoldEffect ( battlerAtk , FALSE ) = = HOLD_EFFECT_GEMS ) )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
break ;
case EFFECT_LOW_KICK :
weight = GetBattlerWeight ( battlerDef ) ;
for ( i = 0 ; sWeightToDamageTable [ i ] ! = 0xFFFF ; i + = 2 )
{
if ( sWeightToDamageTable [ i ] > weight )
break ;
}
if ( sWeightToDamageTable [ i ] ! = 0xFFFF )
basePower = sWeightToDamageTable [ i + 1 ] ;
else
basePower = 120 ;
break ;
case EFFECT_HEAT_CRASH :
weight = GetBattlerWeight ( battlerAtk ) / GetBattlerWeight ( battlerDef ) ;
2021-10-05 01:17:43 +02:00
if ( weight > = ARRAY_COUNT ( sHeatCrashPowerTable ) )
basePower = sHeatCrashPowerTable [ ARRAY_COUNT ( sHeatCrashPowerTable ) - 1 ] ;
2018-07-14 22:56:03 +02:00
else
2021-11-09 18:12:40 +01:00
basePower = sHeatCrashPowerTable [ weight ] ;
2018-07-14 22:56:03 +02:00
break ;
case EFFECT_PUNISHMENT :
2019-11-03 19:58:04 +01:00
basePower = 60 + ( CountBattlerStatIncreases ( battlerDef , FALSE ) * 20 ) ;
2018-07-14 22:56:03 +02:00
if ( basePower > 200 )
basePower = 200 ;
break ;
case EFFECT_STORED_POWER :
2018-11-30 20:52:39 +01:00
basePower + = ( CountBattlerStatIncreases ( battlerAtk , TRUE ) * 20 ) ;
2018-07-14 22:56:03 +02:00
break ;
case EFFECT_ELECTRO_BALL :
speed = GetBattlerTotalSpeedStat ( battlerAtk ) / GetBattlerTotalSpeedStat ( battlerDef ) ;
2019-01-05 19:02:01 +01:00
if ( speed > = ARRAY_COUNT ( sSpeedDiffPowerTable ) )
speed = ARRAY_COUNT ( sSpeedDiffPowerTable ) - 1 ;
basePower = sSpeedDiffPowerTable [ speed ] ;
2018-07-14 22:56:03 +02:00
break ;
case EFFECT_GYRO_BALL :
basePower = ( ( 25 * GetBattlerTotalSpeedStat ( battlerDef ) ) / GetBattlerTotalSpeedStat ( battlerAtk ) ) + 1 ;
if ( basePower > 150 )
basePower = 150 ;
break ;
case EFFECT_ECHOED_VOICE :
2021-09-09 17:15:58 +02:00
// gBattleStruct->sameMoveTurns incremented in ppreduce
if ( gBattleStruct - > sameMoveTurns [ battlerAtk ] ! = 0 )
2018-07-14 22:56:03 +02:00
{
2021-09-09 19:54:16 +02:00
basePower + = ( basePower * gBattleStruct - > sameMoveTurns [ battlerAtk ] ) ;
2021-09-09 19:38:46 +02:00
if ( basePower > 200 )
basePower = 200 ;
2018-07-14 22:56:03 +02:00
}
break ;
case EFFECT_PAYBACK :
2020-04-20 00:00:44 +02:00
if ( GetBattlerTurnOrderNum ( battlerAtk ) > GetBattlerTurnOrderNum ( battlerDef )
& & ( gDisableStructs [ battlerDef ] . isFirstTurn ! = 2 | | B_PAYBACK_SWITCH_BOOST < GEN_5 ) )
2018-07-14 22:56:03 +02:00
basePower * = 2 ;
break ;
2021-11-04 07:50:54 +01:00
case EFFECT_BOLT_BEAK :
if ( GetBattlerTurnOrderNum ( battlerAtk ) < GetBattlerTurnOrderNum ( battlerDef ) )
basePower * = 2 ;
break ;
2018-07-14 22:56:03 +02:00
case EFFECT_ROUND :
if ( gChosenMoveByBattler [ BATTLE_PARTNER ( battlerAtk ) ] = = MOVE_ROUND & & ! ( gAbsentBattlerFlags & gBitTable [ BATTLE_PARTNER ( battlerAtk ) ] ) )
basePower * = 2 ;
break ;
2018-09-30 14:04:46 +02:00
case EFFECT_FUSION_COMBO :
if ( gBattleMoves [ gLastUsedMove ] . effect = = EFFECT_FUSION_COMBO & & move ! = gLastUsedMove )
basePower * = 2 ;
break ;
2021-01-28 20:21:11 +01:00
case EFFECT_LASH_OUT :
2021-09-23 03:15:02 +02:00
if ( gProtectStructs [ battlerAtk ] . statFell )
2021-01-28 20:21:11 +01:00
basePower * = 2 ;
break ;
2021-01-28 21:27:00 +01:00
case EFFECT_EXPLOSION :
if ( move = = MOVE_MISTY_EXPLOSION & & gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN & & IsBattlerGrounded ( battlerAtk ) )
2021-07-25 17:38:54 +02:00
MulModifier ( & basePower , UQ_4_12 ( 1.5 ) ) ;
2021-01-28 21:27:00 +01:00
break ;
2021-07-25 17:38:54 +02:00
case EFFECT_DYNAMAX_DOUBLE_DMG :
2021-01-28 21:27:00 +01:00
# ifdef B_DYNAMAX
2021-07-25 17:38:54 +02:00
if ( IsDynamaxed ( battlerDef ) )
2021-01-28 21:27:00 +01:00
basePower * = 2 ;
# endif
break ;
2021-10-11 01:26:38 +02:00
case EFFECT_HIDDEN_POWER :
{
# if B_HIDDEN_POWER_DMG < GEN_6
u8 powerBits ;
powerBits = ( ( gBattleMons [ gBattlerAttacker ] . hpIV & 2 ) > > 1 )
| ( ( gBattleMons [ gBattlerAttacker ] . attackIV & 2 ) < < 0 )
| ( ( gBattleMons [ gBattlerAttacker ] . defenseIV & 2 ) < < 1 )
| ( ( gBattleMons [ gBattlerAttacker ] . speedIV & 2 ) < < 2 )
| ( ( gBattleMons [ gBattlerAttacker ] . spAttackIV & 2 ) < < 3 )
| ( ( gBattleMons [ gBattlerAttacker ] . spDefenseIV & 2 ) < < 4 ) ;
basePower = ( 40 * powerBits ) / 63 + 30 ;
# endif
break ;
}
2021-10-17 14:27:35 +02:00
case EFFECT_GRAV_APPLE :
if ( gFieldStatuses & STATUS_FIELD_GRAVITY )
MulModifier ( & basePower , UQ_4_12 ( 1.5 ) ) ;
break ;
2021-10-05 03:45:37 +02:00
case EFFECT_TERRAIN_PULSE :
if ( ( gFieldStatuses & STATUS_FIELD_TERRAIN_ANY )
& & IsBattlerGrounded ( gBattlerAttacker ) )
basePower * = 2 ;
break ;
2021-06-15 16:25:59 +02:00
case EFFECT_EXPANDING_FORCE :
2021-11-19 08:20:16 +01:00
if ( IsBattlerTerrainAffected ( gBattlerAttacker , STATUS_FIELD_PSYCHIC_TERRAIN ) )
MulModifier ( & basePower , UQ_4_12 ( 1.5 ) ) ;
2021-06-15 16:25:59 +02:00
break ;
2021-06-15 17:36:50 +02:00
case EFFECT_RISING_VOLTAGE :
2021-11-19 08:20:16 +01:00
if ( IsBattlerTerrainAffected ( gBattlerTarget , STATUS_FIELD_ELECTRIC_TERRAIN ) )
basePower * = 2 ;
2021-06-15 17:36:50 +02:00
break ;
2018-07-14 22:56:03 +02:00
}
2021-11-19 05:48:11 +01:00
// Move-specific base power changes
2021-10-02 03:32:48 +02:00
switch ( move )
{
case MOVE_WATER_SHURIKEN :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_GRENINJA_ASH )
basePower = 20 ;
break ;
2018-07-14 22:56:03 +02:00
}
if ( basePower = = 0 )
basePower = 1 ;
return basePower ;
}
2019-05-07 15:26:58 +02:00
static u32 CalcMoveBasePowerAfterModifiers ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , bool32 updateFlags )
2018-07-14 22:56:03 +02:00
{
2020-07-12 10:09:23 +02:00
u32 i , ability ;
2018-07-14 22:56:03 +02:00
u32 holdEffectAtk , holdEffectParamAtk ;
u16 basePower = CalcMoveBasePower ( move , battlerAtk , battlerDef ) ;
u16 holdEffectModifier ;
u16 modifier = UQ_4_12 ( 1.0 ) ;
2021-10-15 11:00:24 +02:00
u32 atkSide = GET_BATTLER_SIDE ( battlerAtk ) ;
2018-07-14 22:56:03 +02:00
// attacker's abilities
switch ( GetBattlerAbility ( battlerAtk ) )
{
case ABILITY_TECHNICIAN :
if ( basePower < = 60 )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_FLARE_BOOST :
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_BURN & & IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_TOXIC_BOOST :
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_PSN_ANY & & IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_RECKLESS :
if ( gBattleMoves [ move ] . flags & FLAG_RECKLESS_BOOST )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case ABILITY_IRON_FIST :
if ( gBattleMoves [ move ] . flags & FLAG_IRON_FIST_BOOST )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case ABILITY_SHEER_FORCE :
if ( gBattleMoves [ move ] . flags & FLAG_SHEER_FORCE_BOOST )
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
case ABILITY_SAND_FORCE :
2021-02-01 04:43:16 +01:00
if ( ( moveType = = TYPE_STEEL | | moveType = = TYPE_ROCK | | moveType = = TYPE_GROUND )
& & WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SANDSTORM_ANY )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
case ABILITY_RIVALRY :
if ( GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerAtk ] . species , gBattleMons [ battlerAtk ] . personality ) ! = MON_GENDERLESS
& & GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerDef ] . species , gBattleMons [ battlerDef ] . personality ) ! = MON_GENDERLESS )
{
if ( GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerAtk ] . species , gBattleMons [ battlerAtk ] . personality )
= = GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerDef ] . species , gBattleMons [ battlerDef ] . personality ) )
MulModifier ( & modifier , UQ_4_12 ( 1.25 ) ) ;
else
MulModifier ( & modifier , UQ_4_12 ( 0.75 ) ) ;
}
break ;
case ABILITY_ANALYTIC :
if ( GetBattlerTurnOrderNum ( battlerAtk ) = = gBattlersCount - 1 & & move ! = MOVE_FUTURE_SIGHT & & move ! = MOVE_DOOM_DESIRE )
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
case ABILITY_TOUGH_CLAWS :
2021-06-05 22:47:05 +02:00
if ( IsMoveMakingContact ( move , battlerAtk ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
case ABILITY_STRONG_JAW :
if ( gBattleMoves [ move ] . flags & FLAG_STRONG_JAW_BOOST )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_MEGA_LAUNCHER :
if ( gBattleMoves [ move ] . flags & FLAG_MEGA_LAUNCHER_BOOST )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_WATER_BUBBLE :
if ( moveType = = TYPE_WATER )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case ABILITY_STEELWORKER :
if ( moveType = = TYPE_STEEL )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2018-07-28 18:41:57 +02:00
case ABILITY_PIXILATE :
if ( moveType = = TYPE_FAIRY & & gBattleStruct - > ateBoost [ battlerAtk ] )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case ABILITY_GALVANIZE :
if ( moveType = = TYPE_ELECTRIC & & gBattleStruct - > ateBoost [ battlerAtk ] )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case ABILITY_REFRIGERATE :
if ( moveType = = TYPE_ICE & & gBattleStruct - > ateBoost [ battlerAtk ] )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case ABILITY_AERILATE :
if ( moveType = = TYPE_FLYING & & gBattleStruct - > ateBoost [ battlerAtk ] )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case ABILITY_NORMALIZE :
if ( moveType = = TYPE_NORMAL & & gBattleStruct - > ateBoost [ battlerAtk ] )
MulModifier ( & modifier , UQ_4_12 ( 1.2 ) ) ;
break ;
2020-12-11 23:46:33 +01:00
case ABILITY_PUNK_ROCK :
2020-12-19 23:15:12 +01:00
if ( gBattleMoves [ move ] . flags & FLAG_SOUND )
2020-12-11 23:46:33 +01:00
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
2021-01-05 23:44:12 +01:00
case ABILITY_STEELY_SPIRIT :
if ( moveType = = TYPE_STEEL )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_TRANSISTOR :
if ( moveType = = TYPE_ELECTRIC )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_DRAGONS_MAW :
if ( moveType = = TYPE_DRAGON )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2021-10-30 07:31:44 +02:00
case ABILITY_GORILLA_TACTICS :
if ( IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2018-07-14 22:56:03 +02:00
}
// field abilities
2019-03-31 21:38:58 +02:00
if ( ( IsAbilityOnField ( ABILITY_DARK_AURA ) & & moveType = = TYPE_DARK )
| | ( IsAbilityOnField ( ABILITY_FAIRY_AURA ) & & moveType = = TYPE_FAIRY ) )
2018-07-14 22:56:03 +02:00
{
2019-03-31 21:38:58 +02:00
if ( IsAbilityOnField ( ABILITY_AURA_BREAK ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.75 ) ) ;
else
2021-11-15 09:40:20 +01:00
MulModifier ( & modifier , UQ_4_12 ( 1.33 ) ) ;
2018-07-14 22:56:03 +02:00
}
// attacker partner's abilities
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) )
{
switch ( GetBattlerAbility ( BATTLE_PARTNER ( battlerAtk ) ) )
{
case ABILITY_BATTERY :
if ( IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
2021-01-05 23:51:52 +01:00
case ABILITY_POWER_SPOT :
MulModifier ( & modifier , UQ_4_12 ( 1.3 ) ) ;
break ;
2021-01-05 23:44:12 +01:00
case ABILITY_STEELY_SPIRIT :
if ( moveType = = TYPE_STEEL )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2018-07-14 22:56:03 +02:00
}
}
// target's abilities
2020-07-12 10:09:23 +02:00
ability = GetBattlerAbility ( battlerDef ) ;
switch ( ability )
2018-07-14 22:56:03 +02:00
{
case ABILITY_HEATPROOF :
case ABILITY_WATER_BUBBLE :
if ( moveType = = TYPE_FIRE )
2020-07-12 10:09:23 +02:00
{
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
2020-07-12 10:09:23 +02:00
if ( updateFlags )
RecordAbilityBattle ( battlerDef , ability ) ;
}
2018-07-14 22:56:03 +02:00
break ;
case ABILITY_DRY_SKIN :
if ( moveType = = TYPE_FIRE )
MulModifier ( & modifier , UQ_4_12 ( 1.25 ) ) ;
break ;
case ABILITY_FLUFFY :
if ( IsMoveMakingContact ( move , battlerAtk ) )
2020-07-12 10:09:23 +02:00
{
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
2020-07-12 10:09:23 +02:00
if ( updateFlags )
RecordAbilityBattle ( battlerDef , ability ) ;
}
2018-07-14 22:56:03 +02:00
if ( moveType = = TYPE_FIRE )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
}
holdEffectAtk = GetBattlerHoldEffect ( battlerAtk , TRUE ) ;
holdEffectParamAtk = GetBattlerHoldEffectParam ( battlerAtk ) ;
if ( holdEffectParamAtk > 100 )
holdEffectParamAtk = 100 ;
holdEffectModifier = UQ_4_12 ( 1.0 ) + sPercentToModifier [ holdEffectParamAtk ] ;
// attacker's hold effect
switch ( holdEffectAtk )
{
case HOLD_EFFECT_MUSCLE_BAND :
if ( IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
case HOLD_EFFECT_WISE_GLASSES :
if ( IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
case HOLD_EFFECT_LUSTROUS_ORB :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_PALKIA & & ( moveType = = TYPE_WATER | | moveType = = TYPE_DRAGON ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
case HOLD_EFFECT_ADAMANT_ORB :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_DIALGA & & ( moveType = = TYPE_STEEL | | moveType = = TYPE_DRAGON ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
case HOLD_EFFECT_GRISEOUS_ORB :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_GIRATINA & & ( moveType = = TYPE_GHOST | | moveType = = TYPE_DRAGON ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
case HOLD_EFFECT_SOUL_DEW :
2021-11-05 01:00:39 +01:00
# if B_SOUL_DEW_BOOST >= GEN_7
if ( ( gBattleMons [ battlerAtk ] . species = = SPECIES_LATIAS | | gBattleMons [ battlerAtk ] . species = = SPECIES_LATIOS ) & & ( moveType = = TYPE_PSYCHIC | | moveType = = TYPE_DRAGON ) )
# else
2021-11-07 18:40:18 +01:00
if ( ( gBattleMons [ battlerAtk ] . species = = SPECIES_LATIAS | | gBattleMons [ battlerAtk ] . species = = SPECIES_LATIOS ) & & ! ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER ) & & IS_MOVE_SPECIAL ( move ) )
2021-11-05 01:00:39 +01:00
# endif
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
2019-05-07 15:26:58 +02:00
case HOLD_EFFECT_GEMS :
if ( gSpecialStatuses [ battlerAtk ] . gemBoost & & gBattleMons [ battlerAtk ] . item )
MulModifier ( & modifier , UQ_4_12 ( 1.0 ) + sPercentToModifier [ gSpecialStatuses [ battlerAtk ] . gemParam ] ) ;
break ;
2018-07-14 22:56:03 +02:00
case HOLD_EFFECT_BUG_POWER :
case HOLD_EFFECT_STEEL_POWER :
case HOLD_EFFECT_GROUND_POWER :
case HOLD_EFFECT_ROCK_POWER :
case HOLD_EFFECT_GRASS_POWER :
case HOLD_EFFECT_DARK_POWER :
case HOLD_EFFECT_FIGHTING_POWER :
case HOLD_EFFECT_ELECTRIC_POWER :
case HOLD_EFFECT_WATER_POWER :
case HOLD_EFFECT_FLYING_POWER :
case HOLD_EFFECT_POISON_POWER :
case HOLD_EFFECT_ICE_POWER :
case HOLD_EFFECT_GHOST_POWER :
case HOLD_EFFECT_PSYCHIC_POWER :
case HOLD_EFFECT_FIRE_POWER :
case HOLD_EFFECT_DRAGON_POWER :
case HOLD_EFFECT_NORMAL_POWER :
case HOLD_EFFECT_FAIRY_POWER :
for ( i = 0 ; i < ARRAY_COUNT ( sHoldEffectToType ) ; i + + )
{
if ( holdEffectAtk = = sHoldEffectToType [ i ] [ 0 ] )
{
if ( moveType = = sHoldEffectToType [ i ] [ 1 ] )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
}
}
break ;
2020-11-08 08:57:52 +01:00
case HOLD_EFFECT_PLATE :
if ( moveType = = ItemId_GetSecondaryId ( gBattleMons [ battlerAtk ] . item ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
2018-07-14 22:56:03 +02:00
}
// move effect
switch ( gBattleMoves [ move ] . effect )
{
case EFFECT_FACADE :
if ( gBattleMons [ battlerAtk ] . status1 & ( STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS ) )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case EFFECT_BRINE :
2020-05-24 10:05:26 +02:00
if ( gBattleMons [ battlerDef ] . hp < = ( gBattleMons [ battlerDef ] . maxHP / 2 ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case EFFECT_VENOSHOCK :
2021-08-25 12:57:10 +02:00
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_PSN_ANY )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
2021-09-24 16:02:26 +02:00
case EFFECT_RETALIATE :
2021-10-16 10:41:50 +02:00
if ( gSideTimers [ atkSide ] . retaliateTimer = = 1 )
2021-10-11 08:16:59 +02:00
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
2018-07-14 22:56:03 +02:00
break ;
case EFFECT_SOLARBEAM :
2021-05-24 17:52:45 +02:00
if ( IsBattlerWeatherAffected ( battlerAtk , ( WEATHER_HAIL_ANY | WEATHER_SANDSTORM_ANY | WEATHER_RAIN_ANY ) ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
2019-04-01 16:28:17 +02:00
case EFFECT_STOMPING_TANTRUM :
if ( gBattleStruct - > lastMoveFailed & gBitTable [ battlerAtk ] )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
2018-07-14 22:56:03 +02:00
case EFFECT_BULLDOZE :
case EFFECT_MAGNITUDE :
case EFFECT_EARTHQUAKE :
2019-02-28 15:02:54 +01:00
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & ! ( gStatuses3 [ battlerDef ] & STATUS3_SEMI_INVULNERABLE ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case EFFECT_KNOCK_OFF :
2021-11-12 09:05:42 +01:00
# if B_KNOCK_OFF_DMG >= GEN_6
if ( gBattleMons [ battlerDef ] . item ! = ITEM_NONE
& & CanBattlerGetOrLoseItem ( battlerDef , gBattleMons [ battlerDef ] . item ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
2021-11-12 09:05:42 +01:00
# endif
2018-07-14 22:56:03 +02:00
break ;
}
// various effecs
if ( gProtectStructs [ battlerAtk ] . helpingHand )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
if ( gStatuses3 [ battlerAtk ] & STATUS3_CHARGED_UP & & moveType = = TYPE_ELECTRIC )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
if ( gStatuses3 [ battlerAtk ] & STATUS3_ME_FIRST )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
2019-02-28 15:02:54 +01:00
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & moveType = = TYPE_GRASS & & IsBattlerGrounded ( battlerAtk ) & & ! ( gStatuses3 [ battlerAtk ] & STATUS3_SEMI_INVULNERABLE ) )
2020-04-20 14:11:28 +02:00
MulModifier ( & modifier , ( B_TERRAIN_TYPE_BOOST > = GEN_8 ) ? UQ_4_12 ( 1.3 ) : UQ_4_12 ( 1.5 ) ) ;
2019-03-02 23:54:08 +01:00
if ( gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN & & moveType = = TYPE_DRAGON & & IsBattlerGrounded ( battlerDef ) & & ! ( gStatuses3 [ battlerDef ] & STATUS3_SEMI_INVULNERABLE ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
2019-02-28 15:02:54 +01:00
if ( gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN & & moveType = = TYPE_ELECTRIC & & IsBattlerGrounded ( battlerAtk ) & & ! ( gStatuses3 [ battlerAtk ] & STATUS3_SEMI_INVULNERABLE ) )
2020-04-20 14:11:28 +02:00
MulModifier ( & modifier , ( B_TERRAIN_TYPE_BOOST > = GEN_8 ) ? UQ_4_12 ( 1.3 ) : UQ_4_12 ( 1.5 ) ) ;
2019-02-28 15:02:54 +01:00
if ( gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN & & moveType = = TYPE_PSYCHIC & & IsBattlerGrounded ( battlerAtk ) & & ! ( gStatuses3 [ battlerAtk ] & STATUS3_SEMI_INVULNERABLE ) )
2020-04-20 14:11:28 +02:00
MulModifier ( & modifier , ( B_TERRAIN_TYPE_BOOST > = GEN_8 ) ? UQ_4_12 ( 1.3 ) : UQ_4_12 ( 1.5 ) ) ;
2018-07-14 22:56:03 +02:00
return ApplyModifier ( modifier , basePower ) ;
}
2020-07-12 10:09:23 +02:00
static u32 CalcAttackStat ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , bool32 isCrit , bool32 updateFlags )
2018-07-14 22:56:03 +02:00
{
u8 atkStage ;
u32 atkStat ;
u16 modifier ;
if ( gBattleMoves [ move ] . effect = = EFFECT_FOUL_PLAY )
{
if ( IS_MOVE_PHYSICAL ( move ) )
2018-11-17 23:47:35 +01:00
{
2018-07-14 22:56:03 +02:00
atkStat = gBattleMons [ battlerDef ] . attack ;
2018-11-17 23:47:35 +01:00
atkStage = gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] ;
}
2018-07-14 22:56:03 +02:00
else
2018-11-17 23:47:35 +01:00
{
2018-07-14 22:56:03 +02:00
atkStat = gBattleMons [ battlerDef ] . spAttack ;
2018-11-17 23:47:35 +01:00
atkStage = gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] ;
}
2018-07-14 22:56:03 +02:00
}
2021-09-22 05:44:13 +02:00
else if ( gBattleMoves [ move ] . effect = = EFFECT_BODY_PRESS )
2021-03-16 10:56:44 +01:00
{
2021-03-16 11:37:02 +01:00
atkStat = gBattleMons [ battlerAtk ] . defense ;
atkStage = gBattleMons [ battlerAtk ] . statStages [ STAT_DEF ] ;
2021-03-16 10:56:44 +01:00
}
2018-07-14 22:56:03 +02:00
else
{
if ( IS_MOVE_PHYSICAL ( move ) )
2018-11-17 23:47:35 +01:00
{
2018-07-14 22:56:03 +02:00
atkStat = gBattleMons [ battlerAtk ] . attack ;
2018-11-17 23:47:35 +01:00
atkStage = gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] ;
}
2018-07-14 22:56:03 +02:00
else
2018-11-17 23:47:35 +01:00
{
2018-07-14 22:56:03 +02:00
atkStat = gBattleMons [ battlerAtk ] . spAttack ;
2018-11-17 23:47:35 +01:00
atkStage = gBattleMons [ battlerAtk ] . statStages [ STAT_SPATK ] ;
}
2018-07-14 22:56:03 +02:00
}
// critical hits ignore attack stat's stage drops
2021-04-28 03:36:37 +02:00
if ( isCrit & & atkStage < DEFAULT_STAT_STAGE )
atkStage = DEFAULT_STAT_STAGE ;
2018-07-14 22:56:03 +02:00
// pokemon with unaware ignore attack stat changes while taking damage
if ( GetBattlerAbility ( battlerDef ) = = ABILITY_UNAWARE )
2021-04-28 03:36:37 +02:00
atkStage = DEFAULT_STAT_STAGE ;
2018-07-14 22:56:03 +02:00
atkStat * = gStatStageRatios [ atkStage ] [ 0 ] ;
atkStat / = gStatStageRatios [ atkStage ] [ 1 ] ;
// apply attack stat modifiers
modifier = UQ_4_12 ( 1.0 ) ;
// attacker's abilities
switch ( GetBattlerAbility ( battlerAtk ) )
{
case ABILITY_HUGE_POWER :
case ABILITY_PURE_POWER :
if ( IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case ABILITY_SLOW_START :
if ( gDisableStructs [ battlerAtk ] . slowStartTimer ! = 0 )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case ABILITY_SOLAR_POWER :
2021-05-24 17:52:45 +02:00
if ( IS_MOVE_SPECIAL ( move ) & & IsBattlerWeatherAffected ( battlerAtk , WEATHER_SUN_ANY ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_DEFEATIST :
2021-04-01 01:17:05 +02:00
if ( gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerAtk ] . maxHP / 2 ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case ABILITY_FLASH_FIRE :
2018-07-19 21:18:20 +02:00
if ( moveType = = TYPE_FIRE & & gBattleResources - > flags - > flags [ battlerAtk ] & RESOURCE_FLAG_FLASH_FIRE )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_SWARM :
if ( moveType = = TYPE_BUG & & gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerAtk ] . maxHP / 3 ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_TORRENT :
if ( moveType = = TYPE_WATER & & gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerAtk ] . maxHP / 3 ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_BLAZE :
if ( moveType = = TYPE_FIRE & & gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerAtk ] . maxHP / 3 ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_OVERGROW :
if ( moveType = = TYPE_GRASS & & gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerAtk ] . maxHP / 3 ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_PLUS :
case ABILITY_MINUS :
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) )
{
u32 partnerAbility = GetBattlerAbility ( BATTLE_PARTNER ( battlerAtk ) ) ;
if ( partnerAbility = = ABILITY_PLUS | | partnerAbility = = ABILITY_MINUS )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
}
break ;
case ABILITY_FLOWER_GIFT :
2021-05-24 17:52:45 +02:00
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_CHERRIM & & IsBattlerWeatherAffected ( battlerAtk , WEATHER_SUN_ANY ) & & IS_MOVE_PHYSICAL ( move ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_HUSTLE :
if ( IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2020-04-18 19:15:24 +02:00
case ABILITY_STAKEOUT :
if ( gDisableStructs [ battlerDef ] . isFirstTurn = = 2 ) // just switched in
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
2020-11-17 00:22:59 +01:00
case ABILITY_GUTS :
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_ANY & & IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2018-07-14 22:56:03 +02:00
}
// target's abilities
switch ( GetBattlerAbility ( battlerDef ) )
{
case ABILITY_THICK_FAT :
if ( moveType = = TYPE_FIRE | | moveType = = TYPE_ICE )
2020-07-12 10:09:23 +02:00
{
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
2020-07-12 10:09:23 +02:00
if ( updateFlags )
RecordAbilityBattle ( battlerDef , ABILITY_THICK_FAT ) ;
}
2018-07-14 22:56:03 +02:00
break ;
2020-12-12 23:39:35 +01:00
case ABILITY_ICE_SCALES :
if ( IS_MOVE_SPECIAL ( move ) )
2021-06-10 12:55:05 +02:00
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
2020-12-12 23:39:35 +01:00
break ;
2018-07-14 22:56:03 +02:00
}
// ally's abilities
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) )
{
switch ( GetBattlerAbility ( BATTLE_PARTNER ( battlerAtk ) ) )
{
case ABILITY_FLOWER_GIFT :
2021-05-24 17:52:45 +02:00
if ( gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . species = = SPECIES_CHERRIM & & IsBattlerWeatherAffected ( BATTLE_PARTNER ( battlerAtk ) , WEATHER_SUN_ANY ) & & IS_MOVE_PHYSICAL ( move ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
}
// attacker's hold effect
switch ( GetBattlerHoldEffect ( battlerAtk , TRUE ) )
{
case HOLD_EFFECT_THICK_CLUB :
2021-01-20 23:30:48 +01:00
if ( ( GET_BASE_SPECIES_ID ( gBattleMons [ battlerAtk ] . species ) = = SPECIES_CUBONE
| | GET_BASE_SPECIES_ID ( gBattleMons [ battlerAtk ] . species ) = = SPECIES_MAROWAK )
2021-01-03 13:58:19 +01:00
& & IS_MOVE_PHYSICAL ( move ) )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case HOLD_EFFECT_DEEP_SEA_TOOTH :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_CLAMPERL & & IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case HOLD_EFFECT_LIGHT_BALL :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_PIKACHU )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case HOLD_EFFECT_CHOICE_BAND :
if ( IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case HOLD_EFFECT_CHOICE_SPECS :
if ( IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
2020-10-21 20:01:53 +02:00
// The offensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the 1st badge and 7th badges.
// Having the 1st badge boosts physical attack while having the 7th badge boosts special attack.
2020-10-21 21:39:06 +02:00
if ( ShouldGetStatBadgeBoost ( FLAG_BADGE01_GET , battlerAtk ) & & IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.1 ) ) ;
if ( ShouldGetStatBadgeBoost ( FLAG_BADGE07_GET , battlerAtk ) & & IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.1 ) ) ;
2020-10-21 16:44:03 +02:00
2018-07-14 22:56:03 +02:00
return ApplyModifier ( modifier , atkStat ) ;
}
2020-03-14 12:23:51 +01:00
static bool32 CanEvolve ( u32 species )
{
u32 i ;
for ( i = 0 ; i < EVOS_PER_MON ; i + + )
{
2021-08-25 07:16:38 +02:00
if ( gEvolutionTable [ species ] [ i ] . method
& & gEvolutionTable [ species ] [ i ] . method ! = EVO_MEGA_EVOLUTION
2021-08-25 08:35:21 +02:00
& & gEvolutionTable [ species ] [ i ] . method ! = EVO_MOVE_MEGA_EVOLUTION
& & gEvolutionTable [ species ] [ i ] . method ! = EVO_PRIMAL_REVERSION )
2020-03-14 12:23:51 +01:00
return TRUE ;
}
return FALSE ;
}
2020-07-12 10:09:23 +02:00
static u32 CalcDefenseStat ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , bool32 isCrit , bool32 updateFlags )
2018-07-14 22:56:03 +02:00
{
bool32 usesDefStat ;
u8 defStage ;
u32 defStat , def , spDef ;
u16 modifier ;
if ( gFieldStatuses & STATUS_FIELD_WONDER_ROOM ) // the defense stats are swapped
{
def = gBattleMons [ battlerDef ] . spDefense ;
spDef = gBattleMons [ battlerDef ] . defense ;
}
else
{
def = gBattleMons [ battlerDef ] . defense ;
spDef = gBattleMons [ battlerDef ] . spDefense ;
}
if ( gBattleMoves [ move ] . effect = = EFFECT_PSYSHOCK | | IS_MOVE_PHYSICAL ( move ) ) // uses defense stat instead of sp.def
{
defStat = def ;
defStage = gBattleMons [ battlerDef ] . statStages [ STAT_DEF ] ;
usesDefStat = TRUE ;
}
else // is special
{
defStat = spDef ;
defStage = gBattleMons [ battlerDef ] . statStages [ STAT_SPDEF ] ;
usesDefStat = FALSE ;
}
// critical hits ignore positive stat changes
2021-04-28 03:36:37 +02:00
if ( isCrit & & defStage > DEFAULT_STAT_STAGE )
defStage = DEFAULT_STAT_STAGE ;
2018-07-14 22:56:03 +02:00
// pokemon with unaware ignore defense stat changes while dealing damage
if ( GetBattlerAbility ( battlerAtk ) = = ABILITY_UNAWARE )
2021-04-28 03:36:37 +02:00
defStage = DEFAULT_STAT_STAGE ;
2018-07-14 22:56:03 +02:00
// certain moves also ignore stat changes
if ( gBattleMoves [ move ] . flags & FLAG_STAT_STAGES_IGNORED )
2021-04-28 03:36:37 +02:00
defStage = DEFAULT_STAT_STAGE ;
2018-07-14 22:56:03 +02:00
defStat * = gStatStageRatios [ defStage ] [ 0 ] ;
defStat / = gStatStageRatios [ defStage ] [ 1 ] ;
// apply defense stat modifiers
modifier = UQ_4_12 ( 1.0 ) ;
// target's abilities
switch ( GetBattlerAbility ( battlerDef ) )
{
case ABILITY_MARVEL_SCALE :
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_ANY & & usesDefStat )
2020-07-12 10:09:23 +02:00
{
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
2020-07-12 10:09:23 +02:00
if ( updateFlags )
RecordAbilityBattle ( battlerDef , ABILITY_MARVEL_SCALE ) ;
}
2018-07-14 22:56:03 +02:00
break ;
case ABILITY_FUR_COAT :
if ( usesDefStat )
2020-07-12 10:09:23 +02:00
{
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
2020-07-12 10:09:23 +02:00
if ( updateFlags )
RecordAbilityBattle ( battlerDef , ABILITY_FUR_COAT ) ;
}
2018-07-14 22:56:03 +02:00
break ;
case ABILITY_GRASS_PELT :
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & usesDefStat )
2020-07-12 10:09:23 +02:00
{
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
2020-07-12 10:09:23 +02:00
if ( updateFlags )
RecordAbilityBattle ( battlerDef , ABILITY_GRASS_PELT ) ;
}
2018-07-14 22:56:03 +02:00
break ;
case ABILITY_FLOWER_GIFT :
2021-05-24 17:52:45 +02:00
if ( gBattleMons [ battlerDef ] . species = = SPECIES_CHERRIM & & IsBattlerWeatherAffected ( battlerDef , WEATHER_SUN_ANY ) & & ! usesDefStat )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2020-12-11 23:46:33 +01:00
case ABILITY_PUNK_ROCK :
2020-12-19 23:15:12 +01:00
if ( gBattleMoves [ move ] . flags & FLAG_SOUND )
2021-04-02 06:10:20 +02:00
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
2020-12-11 23:46:33 +01:00
break ;
2018-07-14 22:56:03 +02:00
}
// ally's abilities
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerDef ) ) )
{
switch ( GetBattlerAbility ( BATTLE_PARTNER ( battlerDef ) ) )
{
case ABILITY_FLOWER_GIFT :
2021-05-24 17:52:45 +02:00
if ( gBattleMons [ BATTLE_PARTNER ( battlerDef ) ] . species = = SPECIES_CHERRIM & & IsBattlerWeatherAffected ( BATTLE_PARTNER ( battlerDef ) , WEATHER_SUN_ANY ) & & ! usesDefStat )
2018-07-14 22:56:03 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
}
// target's hold effects
switch ( GetBattlerHoldEffect ( battlerDef , TRUE ) )
{
case HOLD_EFFECT_DEEP_SEA_SCALE :
if ( gBattleMons [ battlerDef ] . species = = SPECIES_CLAMPERL & & ! usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case HOLD_EFFECT_METAL_POWDER :
if ( gBattleMons [ battlerDef ] . species = = SPECIES_DITTO & & usesDefStat & & ! ( gBattleMons [ battlerDef ] . status2 & STATUS2_TRANSFORMED ) )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case HOLD_EFFECT_EVIOLITE :
2020-03-14 12:23:51 +01:00
if ( CanEvolve ( gBattleMons [ battlerDef ] . species ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
2018-07-14 22:56:03 +02:00
break ;
case HOLD_EFFECT_ASSAULT_VEST :
if ( ! usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2021-11-05 01:00:39 +01:00
# if B_SOUL_DEW_BOOST <= GEN_6
case HOLD_EFFECT_SOUL_DEW :
if ( ( gBattleMons [ battlerDef ] . species = = SPECIES_LATIAS | | gBattleMons [ battlerDef ] . species = = SPECIES_LATIOS )
& & ! ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER )
& & ! usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
# endif
2018-07-14 22:56:03 +02:00
}
2019-08-05 11:48:50 +02:00
// sandstorm sp.def boost for rock types
2019-08-05 12:15:15 +02:00
if ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_ROCK ) & & WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SANDSTORM_ANY & & ! usesDefStat )
2019-08-05 11:48:50 +02:00
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
2020-10-21 20:01:53 +02:00
// The defensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the 5th badge and 7th badges.
// Having the 5th badge boosts physical defense while having the 7th badge boosts special defense.
2020-10-21 21:39:06 +02:00
if ( ShouldGetStatBadgeBoost ( FLAG_BADGE05_GET , battlerDef ) & & IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.1 ) ) ;
if ( ShouldGetStatBadgeBoost ( FLAG_BADGE07_GET , battlerDef ) & & IS_MOVE_SPECIAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.1 ) ) ;
2020-10-21 16:44:03 +02:00
2018-07-14 22:56:03 +02:00
return ApplyModifier ( modifier , defStat ) ;
}
2019-05-07 15:26:58 +02:00
static u32 CalcFinalDmg ( u32 dmg , u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , u16 typeEffectivenessModifier , bool32 isCrit , bool32 updateFlags )
2018-07-14 22:56:03 +02:00
{
2020-04-22 12:49:25 +02:00
u32 percentBoost ;
2018-07-14 22:56:03 +02:00
u32 abilityAtk = GetBattlerAbility ( battlerAtk ) ;
u32 abilityDef = GetBattlerAbility ( battlerDef ) ;
u32 defSide = GET_BATTLER_SIDE ( battlerDef ) ;
u16 finalModifier = UQ_4_12 ( 1.0 ) ;
2021-10-02 07:01:34 +02:00
u16 itemDef = gBattleMons [ battlerDef ] . item ;
2018-07-14 22:56:03 +02:00
// check multiple targets in double battle
if ( GetMoveTargetCount ( move , battlerAtk , battlerDef ) > = 2 )
MulModifier ( & finalModifier , UQ_4_12 ( 0.75 ) ) ;
// take type effectiveness
MulModifier ( & finalModifier , typeEffectivenessModifier ) ;
// check crit
if ( isCrit )
2020-02-08 09:51:55 +01:00
dmg = ApplyModifier ( ( B_CRIT_MULTIPLIER > = GEN_6 ? UQ_4_12 ( 1.5 ) : UQ_4_12 ( 2.0 ) ) , dmg ) ;
2018-07-14 22:56:03 +02:00
// check burn
2019-08-05 11:30:25 +02:00
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_BURN & & IS_MOVE_PHYSICAL ( move )
& & gBattleMoves [ move ] . effect ! = EFFECT_FACADE & & abilityAtk ! = ABILITY_GUTS )
2018-07-14 22:56:03 +02:00
dmg = ApplyModifier ( UQ_4_12 ( 0.5 ) , dmg ) ;
// check sunny/rain weather
2021-05-24 17:52:45 +02:00
if ( IsBattlerWeatherAffected ( battlerAtk , WEATHER_RAIN_ANY ) )
2018-07-14 22:56:03 +02:00
{
if ( moveType = = TYPE_FIRE )
dmg = ApplyModifier ( UQ_4_12 ( 0.5 ) , dmg ) ;
else if ( moveType = = TYPE_WATER )
dmg = ApplyModifier ( UQ_4_12 ( 1.5 ) , dmg ) ;
}
2021-05-24 17:52:45 +02:00
else if ( IsBattlerWeatherAffected ( battlerAtk , WEATHER_SUN_ANY ) )
2018-07-14 22:56:03 +02:00
{
if ( moveType = = TYPE_FIRE )
dmg = ApplyModifier ( UQ_4_12 ( 1.5 ) , dmg ) ;
else if ( moveType = = TYPE_WATER )
dmg = ApplyModifier ( UQ_4_12 ( 0.5 ) , dmg ) ;
}
// check stab
if ( IS_BATTLER_OF_TYPE ( battlerAtk , moveType ) & & move ! = MOVE_STRUGGLE )
{
if ( abilityAtk = = ABILITY_ADAPTABILITY )
MulModifier ( & finalModifier , UQ_4_12 ( 2.0 ) ) ;
else
MulModifier ( & finalModifier , UQ_4_12 ( 1.5 ) ) ;
}
// reflect, light screen, aurora veil
2020-04-18 20:34:09 +02:00
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 ) )
2021-11-12 23:34:44 +01:00
& & abilityAtk ! = ABILITY_INFILTRATOR
& & ! ( isCrit )
2021-11-12 21:19:06 +01:00
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg )
2018-07-14 22:56:03 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
MulModifier ( & finalModifier , UQ_4_12 ( 0.66 ) ) ;
else
MulModifier ( & finalModifier , UQ_4_12 ( 0.5 ) ) ;
}
// attacker's abilities
switch ( abilityAtk )
{
case ABILITY_TINTED_LENS :
if ( typeEffectivenessModifier < = UQ_4_12 ( 0.5 ) )
MulModifier ( & finalModifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case ABILITY_SNIPER :
if ( isCrit )
MulModifier ( & finalModifier , UQ_4_12 ( 1.5 ) ) ;
break ;
2020-01-18 18:34:04 +01:00
case ABILITY_NEUROFORCE :
if ( typeEffectivenessModifier > = UQ_4_12 ( 2.0 ) )
MulModifier ( & finalModifier , UQ_4_12 ( 1.25 ) ) ;
break ;
2018-07-14 22:56:03 +02:00
}
// target's abilities
switch ( abilityDef )
{
case ABILITY_MULTISCALE :
2020-04-18 20:34:09 +02:00
case ABILITY_SHADOW_SHIELD :
2018-07-14 22:56:03 +02:00
if ( BATTLER_MAX_HP ( battlerDef ) )
MulModifier ( & finalModifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case ABILITY_FILTER :
case ABILITY_SOLID_ROCK :
case ABILITY_PRISM_ARMOR :
if ( typeEffectivenessModifier > = UQ_4_12 ( 2.0 ) )
MulModifier ( & finalModifier , UQ_4_12 ( 0.75 ) ) ;
break ;
}
// target's ally's abilities
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerDef ) ) )
{
switch ( GetBattlerAbility ( BATTLE_PARTNER ( battlerDef ) ) )
{
case ABILITY_FRIEND_GUARD :
MulModifier ( & finalModifier , UQ_4_12 ( 0.75 ) ) ;
break ;
}
}
// attacker's hold effect
switch ( GetBattlerHoldEffect ( battlerAtk , TRUE ) )
{
case HOLD_EFFECT_METRONOME :
2020-04-22 12:49:25 +02:00
percentBoost = min ( ( gBattleStruct - > sameMoveTurns [ battlerAtk ] * GetBattlerHoldEffectParam ( battlerAtk ) ) , 100 ) ;
MulModifier ( & finalModifier , UQ_4_12 ( 1.0 ) + sPercentToModifier [ percentBoost ] ) ;
2018-07-14 22:56:03 +02:00
break ;
case HOLD_EFFECT_EXPERT_BELT :
if ( typeEffectivenessModifier > = UQ_4_12 ( 2.0 ) )
MulModifier ( & finalModifier , UQ_4_12 ( 1.2 ) ) ;
break ;
case HOLD_EFFECT_LIFE_ORB :
MulModifier ( & finalModifier , UQ_4_12 ( 1.3 ) ) ;
break ;
}
// target's hold effect
switch ( GetBattlerHoldEffect ( battlerDef , TRUE ) )
{
2019-05-07 15:26:58 +02:00
// berries reducing dmg
case HOLD_EFFECT_RESIST_BERRY :
if ( moveType = = GetBattlerHoldEffectParam ( battlerDef )
2021-10-02 07:01:34 +02:00
& & ( moveType = = TYPE_NORMAL | | typeEffectivenessModifier > = UQ_4_12 ( 2.0 ) )
& & ! UnnerveOn ( battlerDef , itemDef ) )
2019-05-07 15:26:58 +02:00
{
2021-01-06 06:21:38 +01:00
if ( abilityDef = = ABILITY_RIPEN )
MulModifier ( & finalModifier , UQ_4_12 ( 0.25 ) ) ;
else
MulModifier ( & finalModifier , UQ_4_12 ( 0.5 ) ) ;
2019-05-07 15:26:58 +02:00
if ( updateFlags )
2021-09-23 04:29:00 +02:00
gSpecialStatuses [ battlerDef ] . berryReduced = TRUE ;
2019-05-07 15:26:58 +02:00
}
break ;
2018-07-14 22:56:03 +02:00
}
if ( gBattleMoves [ move ] . flags & FLAG_DMG_MINIMIZE & & gStatuses3 [ battlerDef ] & STATUS3_MINIMIZED )
MulModifier ( & finalModifier , UQ_4_12 ( 2.0 ) ) ;
if ( gBattleMoves [ move ] . flags & FLAG_DMG_UNDERGROUND & & gStatuses3 [ battlerDef ] & STATUS3_UNDERGROUND )
MulModifier ( & finalModifier , UQ_4_12 ( 2.0 ) ) ;
if ( gBattleMoves [ move ] . flags & FLAG_DMG_UNDERWATER & & gStatuses3 [ battlerDef ] & STATUS3_UNDERWATER )
MulModifier ( & finalModifier , UQ_4_12 ( 2.0 ) ) ;
2021-06-05 04:26:15 +02:00
if ( gBattleMoves [ move ] . flags & FLAG_DMG_2X_IN_AIR & & gStatuses3 [ battlerDef ] & STATUS3_ON_AIR )
2020-04-11 11:47:13 +02:00
MulModifier ( & finalModifier , UQ_4_12 ( 2.0 ) ) ;
2018-07-14 22:56:03 +02:00
dmg = ApplyModifier ( finalModifier , dmg ) ;
if ( dmg = = 0 )
dmg = 1 ;
return dmg ;
}
2019-04-02 00:14:01 +02:00
s32 CalculateMoveDamage ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , s32 fixedBasePower , bool32 isCrit , bool32 randomFactor , bool32 updateFlags )
2018-07-14 22:56:03 +02:00
{
s32 dmg ;
2019-04-02 00:17:15 +02:00
u16 typeEffectivenessModifier ;
2018-07-14 22:56:03 +02:00
2019-04-02 00:14:01 +02:00
typeEffectivenessModifier = CalcTypeEffectivenessMultiplier ( move , moveType , battlerAtk , battlerDef , updateFlags ) ;
2018-07-14 22:56:03 +02:00
// Don't calculate damage if the move has no effect on target.
if ( typeEffectivenessModifier = = UQ_4_12 ( 0 ) )
return 0 ;
if ( fixedBasePower )
gBattleMovePower = fixedBasePower ;
else
2019-05-07 15:26:58 +02:00
gBattleMovePower = CalcMoveBasePowerAfterModifiers ( move , battlerAtk , battlerDef , moveType , updateFlags ) ;
2018-07-14 22:56:03 +02:00
// long dmg basic formula
dmg = ( ( gBattleMons [ battlerAtk ] . level * 2 ) / 5 ) + 2 ;
dmg * = gBattleMovePower ;
2020-07-12 10:09:23 +02:00
dmg * = CalcAttackStat ( move , battlerAtk , battlerDef , moveType , isCrit , updateFlags ) ;
dmg / = CalcDefenseStat ( move , battlerAtk , battlerDef , moveType , isCrit , updateFlags ) ;
2018-07-14 22:56:03 +02:00
dmg = ( dmg / 50 ) + 2 ;
// Calculate final modifiers.
2019-05-07 15:26:58 +02:00
dmg = CalcFinalDmg ( dmg , move , battlerAtk , battlerDef , moveType , typeEffectivenessModifier , isCrit , updateFlags ) ;
2018-07-14 22:56:03 +02:00
// Add a random factor.
if ( randomFactor )
{
dmg * = 100 - ( Random ( ) % 16 ) ;
dmg / = 100 ;
}
if ( dmg = = 0 )
dmg = 1 ;
return dmg ;
}
2019-05-16 10:40:44 +02:00
static void MulByTypeEffectiveness ( u16 * modifier , u16 move , u8 moveType , u8 battlerDef , u8 defType , u8 battlerAtk , bool32 recordAbilities )
2018-07-14 22:56:03 +02:00
{
2020-07-17 20:53:22 +02:00
u16 mod = GetTypeModifier ( moveType , defType ) ;
2018-07-14 22:56:03 +02:00
2019-05-16 10:40:44 +02:00
if ( mod = = UQ_4_12 ( 0.0 ) & & GetBattlerHoldEffect ( battlerDef , TRUE ) = = HOLD_EFFECT_RING_TARGET )
{
mod = UQ_4_12 ( 1.0 ) ;
if ( recordAbilities )
RecordItemEffectBattle ( battlerDef , HOLD_EFFECT_RING_TARGET ) ;
}
2020-07-17 20:53:22 +02:00
else if ( ( moveType = = TYPE_FIGHTING | | moveType = = TYPE_NORMAL ) & & defType = = TYPE_GHOST & & gBattleMons [ battlerDef ] . status2 & STATUS2_FORESIGHT & & mod = = UQ_4_12 ( 0.0 ) )
2019-05-16 10:40:44 +02:00
{
2018-07-14 22:56:03 +02:00
mod = UQ_4_12 ( 1.0 ) ;
2019-05-16 10:40:44 +02:00
}
2020-07-17 20:53:22 +02:00
else if ( ( moveType = = TYPE_FIGHTING | | moveType = = TYPE_NORMAL ) & & defType = = TYPE_GHOST & & GetBattlerAbility ( battlerAtk ) = = ABILITY_SCRAPPY & & mod = = UQ_4_12 ( 0.0 ) )
2019-05-16 10:40:44 +02:00
{
2018-07-22 19:34:13 +02:00
mod = UQ_4_12 ( 1.0 ) ;
2019-05-16 10:40:44 +02:00
if ( recordAbilities )
RecordAbilityBattle ( battlerAtk , ABILITY_SCRAPPY ) ;
}
2020-07-17 20:53:22 +02:00
if ( moveType = = TYPE_PSYCHIC & & defType = = TYPE_DARK & & gStatuses3 [ battlerDef ] & STATUS3_MIRACLE_EYED & & mod = = UQ_4_12 ( 0.0 ) )
2018-07-14 22:56:03 +02:00
mod = UQ_4_12 ( 1.0 ) ;
2018-08-04 23:34:29 +02:00
if ( gBattleMoves [ move ] . effect = = EFFECT_FREEZE_DRY & & defType = = TYPE_WATER )
2018-07-14 22:56:03 +02:00
mod = UQ_4_12 ( 2.0 ) ;
2020-07-17 20:53:22 +02:00
if ( moveType = = TYPE_GROUND & & defType = = TYPE_FLYING & & IsBattlerGrounded ( battlerDef ) & & mod = = UQ_4_12 ( 0.0 ) )
2018-07-31 23:21:42 +02:00
mod = UQ_4_12 ( 1.0 ) ;
2021-11-10 09:11:15 +01:00
if ( moveType = = TYPE_FIRE & & gDisableStructs [ battlerDef ] . tarShot )
mod = UQ_4_12 ( 2.0 ) ;
2019-05-07 15:26:58 +02:00
2021-10-06 11:32:06 +02:00
// WEATHER_STRONG_WINDS weakens Super Effective moves against Flying-type Pokémon
if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_STRONG_WINDS )
{
if ( defType = = TYPE_FLYING & & mod > = UQ_4_12 ( 2.0 ) )
mod = UQ_4_12 ( 1.0 ) ;
}
2018-07-14 22:56:03 +02:00
MulModifier ( modifier , mod ) ;
}
2018-07-15 12:39:07 +02:00
static void UpdateMoveResultFlags ( u16 modifier )
{
if ( modifier = = UQ_4_12 ( 0.0 ) )
{
gMoveResultFlags | = MOVE_RESULT_DOESNT_AFFECT_FOE ;
gMoveResultFlags & = ~ ( MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE ) ;
}
else if ( modifier = = UQ_4_12 ( 1.0 ) )
{
gMoveResultFlags & = ~ ( MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE ) ;
}
else if ( modifier > UQ_4_12 ( 1.0 ) )
{
gMoveResultFlags | = MOVE_RESULT_SUPER_EFFECTIVE ;
gMoveResultFlags & = ~ ( MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE ) ;
}
else //if (modifier < UQ_4_12(1.0))
{
gMoveResultFlags | = MOVE_RESULT_NOT_VERY_EFFECTIVE ;
gMoveResultFlags & = ~ ( MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE ) ;
}
}
2018-08-05 13:57:37 +02:00
static u16 CalcTypeEffectivenessMultiplierInternal ( u16 move , u8 moveType , u8 battlerAtk , u8 battlerDef , bool32 recordAbilities , u16 modifier )
2018-07-14 19:29:25 +02:00
{
2019-05-16 10:40:44 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , battlerDef , gBattleMons [ battlerDef ] . type1 , battlerAtk , recordAbilities ) ;
2018-08-05 13:57:37 +02:00
if ( gBattleMons [ battlerDef ] . type2 ! = gBattleMons [ battlerDef ] . type1 )
2019-05-16 10:40:44 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , battlerDef , gBattleMons [ battlerDef ] . type2 , battlerAtk , recordAbilities ) ;
2018-11-17 12:10:24 +01:00
if ( gBattleMons [ battlerDef ] . type3 ! = TYPE_MYSTERY & & gBattleMons [ battlerDef ] . type3 ! = gBattleMons [ battlerDef ] . type2
& & gBattleMons [ battlerDef ] . type3 ! = gBattleMons [ battlerDef ] . type1 )
2019-05-16 10:40:44 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , battlerDef , gBattleMons [ battlerDef ] . type3 , battlerAtk , recordAbilities ) ;
2018-07-14 22:56:03 +02:00
2021-06-05 02:34:37 +02:00
if ( moveType = = TYPE_GROUND & & ! IsBattlerGrounded ( battlerDef ) & & ! ( gBattleMoves [ move ] . flags & FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING ) )
2018-07-14 22:56:03 +02:00
{
2018-08-05 13:57:37 +02:00
modifier = UQ_4_12 ( 0.0 ) ;
if ( recordAbilities & & GetBattlerAbility ( battlerDef ) = = ABILITY_LEVITATE )
2018-07-14 22:56:03 +02:00
{
2018-08-05 13:57:37 +02:00
gLastUsedAbility = ABILITY_LEVITATE ;
gMoveResultFlags | = ( MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE ) ;
gLastLandedMoves [ battlerDef ] = 0 ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MISS_TYPE ] = B_MSG_GROUND_MISS ;
2018-08-05 13:57:37 +02:00
RecordAbilityBattle ( battlerDef , ABILITY_LEVITATE ) ;
2018-07-14 22:56:03 +02:00
}
2018-08-05 13:57:37 +02:00
}
2021-04-01 06:23:47 +02:00
// Thousand Arrows ignores type modifiers for flying mons
2021-06-05 02:34:37 +02:00
if ( ! IsBattlerGrounded ( battlerDef ) & & ( gBattleMoves [ move ] . flags & FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING )
2021-04-01 06:23:47 +02:00
& & ( gBattleMons [ battlerDef ] . type1 = = TYPE_FLYING | | gBattleMons [ battlerDef ] . type2 = = TYPE_FLYING | | gBattleMons [ battlerDef ] . type3 = = TYPE_FLYING ) )
{
modifier = UQ_4_12 ( 1.0 ) ;
}
2021-09-22 03:57:05 +02:00
if ( ( ( GetBattlerAbility ( battlerDef ) = = ABILITY_WONDER_GUARD & & modifier < = UQ_4_12 ( 1.0 ) )
| | ( GetBattlerAbility ( battlerDef ) = = ABILITY_TELEPATHY & & battlerDef = = BATTLE_PARTNER ( battlerAtk ) ) )
& & gBattleMoves [ move ] . power )
2018-08-05 13:57:37 +02:00
{
modifier = UQ_4_12 ( 0.0 ) ;
if ( recordAbilities )
2018-07-14 22:56:03 +02:00
{
2021-09-22 03:57:05 +02:00
gLastUsedAbility = gBattleMons [ battlerDef ] . ability ;
2018-08-05 13:57:37 +02:00
gMoveResultFlags | = MOVE_RESULT_MISSED ;
gLastLandedMoves [ battlerDef ] = 0 ;
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MISS_TYPE ] = B_MSG_AVOIDED_DMG ;
2021-09-22 03:57:05 +02:00
RecordAbilityBattle ( battlerDef , gBattleMons [ battlerDef ] . ability ) ;
2018-07-14 22:56:03 +02:00
}
}
2018-08-05 13:57:37 +02:00
return modifier ;
}
u16 CalcTypeEffectivenessMultiplier ( u16 move , u8 moveType , u8 battlerAtk , u8 battlerDef , bool32 recordAbilities )
{
u16 modifier = UQ_4_12 ( 1.0 ) ;
if ( move ! = MOVE_STRUGGLE & & moveType ! = TYPE_MYSTERY )
{
modifier = CalcTypeEffectivenessMultiplierInternal ( move , moveType , battlerAtk , battlerDef , recordAbilities , modifier ) ;
if ( gBattleMoves [ move ] . effect = = EFFECT_TWO_TYPED_MOVE )
modifier = CalcTypeEffectivenessMultiplierInternal ( move , gBattleMoves [ move ] . argument , battlerAtk , battlerDef , recordAbilities , modifier ) ;
}
2019-04-02 00:14:01 +02:00
if ( recordAbilities )
UpdateMoveResultFlags ( modifier ) ;
2018-07-15 12:39:07 +02:00
return modifier ;
}
2020-05-18 23:54:12 +02:00
u16 CalcPartyMonTypeEffectivenessMultiplier ( u16 move , u16 speciesDef , u16 abilityDef )
2018-07-15 12:39:07 +02:00
{
u16 modifier = UQ_4_12 ( 1.0 ) ;
u8 moveType = gBattleMoves [ move ] . type ;
if ( move ! = MOVE_STRUGGLE & & moveType ! = TYPE_MYSTERY )
2018-07-14 22:56:03 +02:00
{
2019-05-16 10:40:44 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , 0 , gBaseStats [ speciesDef ] . type1 , 0 , FALSE ) ;
2018-07-15 12:39:07 +02:00
if ( gBaseStats [ speciesDef ] . type2 ! = gBaseStats [ speciesDef ] . type1 )
2019-05-16 10:40:44 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , 0 , gBaseStats [ speciesDef ] . type2 , 0 , FALSE ) ;
2018-07-15 12:39:07 +02:00
if ( moveType = = TYPE_GROUND & & abilityDef = = ABILITY_LEVITATE & & ! ( gFieldStatuses & STATUS_FIELD_GRAVITY ) )
modifier = UQ_4_12 ( 0.0 ) ;
if ( abilityDef = = ABILITY_WONDER_GUARD & & modifier < = UQ_4_12 ( 1.0 ) & & gBattleMoves [ move ] . power )
modifier = UQ_4_12 ( 0.0 ) ;
2018-07-14 22:56:03 +02:00
}
2018-07-14 19:29:25 +02:00
2018-07-15 12:39:07 +02:00
UpdateMoveResultFlags ( modifier ) ;
2018-07-14 22:56:03 +02:00
return modifier ;
2018-07-14 19:29:25 +02:00
}
2018-07-15 12:39:07 +02:00
u16 GetTypeModifier ( u8 atkType , u8 defType )
{
2020-07-17 20:53:22 +02:00
if ( B_FLAG_INVERSE_BATTLE ! = 0 & & FlagGet ( B_FLAG_INVERSE_BATTLE ) )
return sInverseTypeEffectivenessTable [ atkType ] [ defType ] ;
else
return sTypeEffectivenessTable [ atkType ] [ defType ] ;
2018-07-15 12:39:07 +02:00
}
2018-07-24 21:47:00 +02:00
s32 GetStealthHazardDamage ( u8 hazardType , u8 battlerId )
{
u8 type1 = gBattleMons [ battlerId ] . type1 ;
u8 type2 = gBattleMons [ battlerId ] . type2 ;
u32 maxHp = gBattleMons [ battlerId ] . maxHP ;
s32 dmg = 0 ;
u16 modifier = UQ_4_12 ( 1.0 ) ;
MulModifier ( & modifier , GetTypeModifier ( hazardType , type1 ) ) ;
if ( type2 ! = type1 )
MulModifier ( & modifier , GetTypeModifier ( hazardType , type2 ) ) ;
switch ( modifier )
{
case UQ_4_12 ( 0.0 ) :
dmg = 0 ;
break ;
case UQ_4_12 ( 0.25 ) :
dmg = maxHp / 32 ;
if ( dmg = = 0 )
dmg = 1 ;
break ;
case UQ_4_12 ( 0.5 ) :
dmg = maxHp / 16 ;
if ( dmg = = 0 )
dmg = 1 ;
break ;
case UQ_4_12 ( 1.0 ) :
dmg = maxHp / 8 ;
if ( dmg = = 0 )
dmg = 1 ;
break ;
case UQ_4_12 ( 2.0 ) :
dmg = maxHp / 4 ;
if ( dmg = = 0 )
dmg = 1 ;
break ;
case UQ_4_12 ( 4.0 ) :
dmg = maxHp / 2 ;
if ( dmg = = 0 )
dmg = 1 ;
break ;
}
return dmg ;
}
2018-09-16 18:55:32 +02:00
2020-12-09 18:28:18 +01:00
bool32 IsPartnerMonFromSameTrainer ( u8 battlerId )
2018-09-16 18:55:32 +02:00
{
if ( GetBattlerSide ( battlerId ) = = B_SIDE_OPPONENT & & gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS )
return FALSE ;
else if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER & & gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
return FALSE ;
else if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
return FALSE ;
else
return TRUE ;
}
2018-09-20 11:23:12 +02:00
u16 GetMegaEvolutionSpecies ( u16 preEvoSpecies , u16 heldItemId )
2018-09-16 18:55:32 +02:00
{
u32 i ;
2018-09-20 11:23:12 +02:00
for ( i = 0 ; i < EVOS_PER_MON ; i + + )
{
2021-08-25 08:35:21 +02:00
if ( ( gEvolutionTable [ preEvoSpecies ] [ i ] . method = = EVO_MEGA_EVOLUTION
| | gEvolutionTable [ preEvoSpecies ] [ i ] . method = = EVO_PRIMAL_REVERSION )
& & gEvolutionTable [ preEvoSpecies ] [ i ] . param = = heldItemId )
return gEvolutionTable [ preEvoSpecies ] [ i ] . targetSpecies ;
2018-09-20 11:23:12 +02:00
}
return SPECIES_NONE ;
}
2020-11-07 13:53:34 +01:00
u16 GetWishMegaEvolutionSpecies ( u16 preEvoSpecies , u16 moveId1 , u16 moveId2 , u16 moveId3 , u16 moveId4 )
{
u32 i , par ;
for ( i = 0 ; i < EVOS_PER_MON ; i + + )
{
2020-11-09 01:08:58 +01:00
if ( gEvolutionTable [ preEvoSpecies ] [ i ] . method = = EVO_MOVE_MEGA_EVOLUTION )
2020-11-07 13:53:34 +01:00
{
par = gEvolutionTable [ preEvoSpecies ] [ i ] . param ;
if ( par = = moveId1 | | par = = moveId2 | | par = = moveId3 | | par = = moveId4 )
return gEvolutionTable [ preEvoSpecies ] [ i ] . targetSpecies ;
}
}
return SPECIES_NONE ;
}
2018-09-20 11:23:12 +02:00
bool32 CanMegaEvolve ( u8 battlerId )
{
2020-11-07 13:53:34 +01:00
u32 itemId , holdEffect , species ;
2018-09-20 11:23:12 +02:00
struct Pokemon * mon ;
2018-09-16 18:55:32 +02:00
u8 battlerPosition = GetBattlerPosition ( battlerId ) ;
u8 partnerPosition = GetBattlerPosition ( BATTLE_PARTNER ( battlerId ) ) ;
2019-01-05 16:00:57 +01:00
struct MegaEvolutionData * mega = & ( ( ( struct ChooseMoveStruct * ) ( & gBattleResources - > bufferA [ gActiveBattler ] [ 4 ] ) ) - > mega ) ;
2018-09-16 18:55:32 +02:00
2021-03-10 12:52:43 +01:00
# ifdef ITEM_EXPANSION
2021-11-13 16:10:20 +01:00
// Check if Player has a Mega Ring
2021-03-10 12:52:43 +01:00
if ( ( GetBattlerPosition ( battlerId ) = = B_POSITION_PLAYER_LEFT | | ( ! ( gBattleTypeFlags & BATTLE_TYPE_MULTI ) & & GetBattlerPosition ( battlerId ) = = B_POSITION_PLAYER_RIGHT ) )
2021-11-13 16:10:20 +01:00
& & ! CheckBagHasItem ( ITEM_MEGA_RING , 1 ) )
2021-03-10 12:52:43 +01:00
return FALSE ;
# endif
2018-09-16 18:55:32 +02:00
// Check if trainer already mega evolved a pokemon.
2018-09-20 17:59:17 +02:00
if ( mega - > alreadyEvolved [ battlerPosition ] )
2018-09-16 18:55:32 +02:00
return FALSE ;
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
2018-09-20 12:55:12 +02:00
if ( IsPartnerMonFromSameTrainer ( battlerId )
2018-09-20 17:59:17 +02:00
& & ( mega - > alreadyEvolved [ partnerPosition ] | | ( mega - > toEvolve & gBitTable [ BATTLE_PARTNER ( battlerId ) ] ) ) )
2018-09-16 18:55:32 +02:00
return FALSE ;
}
2020-11-07 13:53:34 +01:00
// Gets mon data.
2018-09-20 11:23:12 +02:00
if ( GetBattlerSide ( battlerId ) = = B_SIDE_OPPONENT )
mon = & gEnemyParty [ gBattlerPartyIndexes [ battlerId ] ] ;
else
mon = & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] ;
2020-11-07 13:53:34 +01:00
species = GetMonData ( mon , MON_DATA_SPECIES ) ;
2018-09-20 11:23:12 +02:00
itemId = GetMonData ( mon , MON_DATA_HELD_ITEM ) ;
2020-11-07 13:53:34 +01:00
// Check if there is an entry in the evolution table for regular Mega Evolution.
if ( GetMegaEvolutionSpecies ( species , itemId ) ! = SPECIES_NONE )
{
2020-12-23 18:04:14 +01:00
if ( B_ENABLE_DEBUG & & gBattleStruct - > debugHoldEffects [ battlerId ] )
2020-11-07 13:53:34 +01:00
holdEffect = gBattleStruct - > debugHoldEffects [ battlerId ] ;
else if ( itemId = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ battlerId ] . holdEffect ;
else
holdEffect = ItemId_GetHoldEffect ( itemId ) ;
2018-09-16 18:55:32 +02:00
2021-08-25 08:35:21 +02:00
// Can Mega Evolve via Mega Stone.
2020-11-07 13:53:34 +01:00
if ( holdEffect = = HOLD_EFFECT_MEGA_STONE )
{
gBattleStruct - > mega . isWishMegaEvo = FALSE ;
return TRUE ;
}
2021-08-25 08:35:21 +02:00
// Can undergo Primal Reversion.
if ( holdEffect = = HOLD_EFFECT_PRIMAL_ORB )
{
gBattleStruct - > mega . isWishMegaEvo = FALSE ;
gBattleStruct - > mega . isPrimalReversion = TRUE ;
return TRUE ;
}
2020-11-07 13:53:34 +01:00
}
// Check if there is an entry in the evolution table for Wish Mega Evolution.
if ( GetWishMegaEvolutionSpecies ( species , GetMonData ( mon , MON_DATA_MOVE1 ) , GetMonData ( mon , MON_DATA_MOVE2 ) , GetMonData ( mon , MON_DATA_MOVE3 ) , GetMonData ( mon , MON_DATA_MOVE4 ) ) )
{
gBattleStruct - > mega . isWishMegaEvo = TRUE ;
return TRUE ;
}
2018-09-16 18:55:32 +02:00
2020-11-07 13:53:34 +01:00
// No checks passed, the mon CAN'T mega evolve.
return FALSE ;
2018-09-16 18:55:32 +02:00
}
2018-09-16 21:08:49 +02:00
2019-12-31 19:11:53 +01:00
void UndoMegaEvolution ( u32 monId )
2018-09-16 21:08:49 +02:00
{
2021-08-25 08:35:21 +02:00
u16 baseSpecies = GET_BASE_SPECIES_ID ( GetMonData ( & gPlayerParty [ monId ] , MON_DATA_SPECIES ) ) ;
2018-09-20 17:33:27 +02:00
if ( gBattleStruct - > mega . evolvedPartyIds [ B_SIDE_PLAYER ] & gBitTable [ monId ] )
2018-09-16 21:08:49 +02:00
{
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . evolvedPartyIds [ B_SIDE_PLAYER ] & = ~ ( gBitTable [ monId ] ) ;
SetMonData ( & gPlayerParty [ monId ] , MON_DATA_SPECIES , & gBattleStruct - > mega . playerEvolvedSpecies ) ;
2018-09-16 21:08:49 +02:00
CalculateMonStats ( & gPlayerParty [ monId ] ) ;
}
2021-08-25 08:35:21 +02:00
else if ( gBattleStruct - > mega . primalRevertedPartyIds [ B_SIDE_PLAYER ] & gBitTable [ monId ] )
{
gBattleStruct - > mega . primalRevertedPartyIds [ B_SIDE_PLAYER ] & = ~ ( gBitTable [ monId ] ) ;
SetMonData ( & gPlayerParty [ monId ] , MON_DATA_SPECIES , & baseSpecies ) ;
CalculateMonStats ( & gPlayerParty [ monId ] ) ;
}
2020-07-16 15:40:56 +02:00
// While not exactly a mega evolution, Zygarde follows the same rules.
else if ( GetMonData ( & gPlayerParty [ monId ] , MON_DATA_SPECIES , NULL ) = = SPECIES_ZYGARDE_COMPLETE )
{
SetMonData ( & gPlayerParty [ monId ] , MON_DATA_SPECIES , & gBattleStruct - > changedSpecies [ monId ] ) ;
gBattleStruct - > changedSpecies [ monId ] = 0 ;
CalculateMonStats ( & gPlayerParty [ monId ] ) ;
}
2018-09-16 21:08:49 +02:00
}
2018-09-29 15:43:56 +02:00
2021-07-16 07:56:53 +02:00
void UndoFormChange ( u32 monId , u32 side , bool32 isSwitchingOut )
2019-12-31 19:11:53 +01:00
{
u32 i , currSpecies ;
struct Pokemon * party = ( side = = B_SIDE_PLAYER ) ? gPlayerParty : gEnemyParty ;
2021-11-04 02:05:02 +01:00
static const u16 species [ ] [ 3 ] =
{
// Changed Form ID Default Form ID Should change on switch
{ SPECIES_MIMIKYU_BUSTED , SPECIES_MIMIKYU , FALSE } ,
{ SPECIES_GRENINJA_ASH , SPECIES_GRENINJA_BATTLE_BOND , FALSE } ,
2021-11-05 23:52:51 +01:00
{ SPECIES_MELOETTA_PIROUETTE , SPECIES_MELOETTA , FALSE } ,
2021-11-04 02:05:02 +01:00
{ SPECIES_AEGISLASH_BLADE , SPECIES_AEGISLASH , TRUE } ,
{ SPECIES_DARMANITAN_ZEN_MODE , SPECIES_DARMANITAN , TRUE } ,
{ SPECIES_MINIOR , SPECIES_MINIOR_CORE_RED , TRUE } ,
{ SPECIES_MINIOR_METEOR_BLUE , SPECIES_MINIOR_CORE_BLUE , TRUE } ,
{ SPECIES_MINIOR_METEOR_GREEN , SPECIES_MINIOR_CORE_GREEN , TRUE } ,
{ SPECIES_MINIOR_METEOR_INDIGO , SPECIES_MINIOR_CORE_INDIGO , TRUE } ,
{ SPECIES_MINIOR_METEOR_ORANGE , SPECIES_MINIOR_CORE_ORANGE , TRUE } ,
{ SPECIES_MINIOR_METEOR_VIOLET , SPECIES_MINIOR_CORE_VIOLET , TRUE } ,
{ SPECIES_MINIOR_METEOR_YELLOW , SPECIES_MINIOR_CORE_YELLOW , TRUE } ,
{ SPECIES_WISHIWASHI_SCHOOL , SPECIES_WISHIWASHI , TRUE } ,
{ SPECIES_CRAMORANT_GORGING , SPECIES_CRAMORANT , TRUE } ,
{ SPECIES_CRAMORANT_GULPING , SPECIES_CRAMORANT , TRUE } ,
2021-11-05 02:32:33 +01:00
{ SPECIES_MORPEKO_HANGRY , SPECIES_MORPEKO , TRUE } ,
2019-12-31 19:11:53 +01:00
} ;
currSpecies = GetMonData ( & party [ monId ] , MON_DATA_SPECIES , NULL ) ;
for ( i = 0 ; i < ARRAY_COUNT ( species ) ; i + + )
{
2021-11-04 02:05:02 +01:00
if ( currSpecies = = species [ i ] [ 0 ] & & ( ! isSwitchingOut | | species [ i ] [ 2 ] = = TRUE ) )
2019-12-31 19:11:53 +01:00
{
SetMonData ( & party [ monId ] , MON_DATA_SPECIES , & species [ i ] [ 1 ] ) ;
CalculateMonStats ( & party [ monId ] ) ;
break ;
}
}
}
2018-09-29 15:43:56 +02:00
bool32 DoBattlersShareType ( u32 battler1 , u32 battler2 )
{
2019-03-08 10:30:23 +01:00
s32 i ;
u8 types1 [ 3 ] = { gBattleMons [ battler1 ] . type1 , gBattleMons [ battler1 ] . type2 , gBattleMons [ battler1 ] . type3 } ;
u8 types2 [ 3 ] = { gBattleMons [ battler2 ] . type1 , gBattleMons [ battler2 ] . type2 , gBattleMons [ battler2 ] . type3 } ;
if ( types1 [ 2 ] = = TYPE_MYSTERY )
types1 [ 2 ] = types1 [ 0 ] ;
if ( types2 [ 2 ] = = TYPE_MYSTERY )
types2 [ 2 ] = types2 [ 0 ] ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( types1 [ i ] = = types2 [ 0 ] | | types1 [ i ] = = types2 [ 1 ] | | types1 [ i ] = = types2 [ 2 ] )
return TRUE ;
}
return FALSE ;
2018-09-29 15:43:56 +02:00
}
2018-09-30 12:27:51 +02:00
bool32 CanBattlerGetOrLoseItem ( u8 battlerId , u16 itemId )
{
u16 species = gBattleMons [ battlerId ] . species ;
2020-12-09 18:28:18 +01:00
u16 holdEffect = ItemId_GetHoldEffect ( itemId ) ;
// Mail can be stolen now
if ( itemId = = ITEM_ENIGMA_BERRY )
2018-09-30 12:27:51 +02:00
return FALSE ;
2021-01-22 05:28:19 +01:00
else if ( GET_BASE_SPECIES_ID ( species ) = = SPECIES_KYOGRE & & itemId = = ITEM_BLUE_ORB ) // includes primal
2018-09-30 12:27:51 +02:00
return FALSE ;
2021-01-22 05:28:19 +01:00
else if ( GET_BASE_SPECIES_ID ( species ) = = SPECIES_GROUDON & & itemId = = ITEM_RED_ORB ) // includes primal
2018-09-30 12:27:51 +02:00
return FALSE ;
2021-08-12 20:44:53 +02:00
// Mega stone cannot be lost if pokemon's base species can mega evolve with it.
else if ( holdEffect = = HOLD_EFFECT_MEGA_STONE & & ( GetMegaEvolutionSpecies ( GET_BASE_SPECIES_ID ( species ) , itemId ) ! = SPECIES_NONE ) )
2018-09-30 12:27:51 +02:00
return FALSE ;
2021-01-20 22:28:03 +01:00
else if ( GET_BASE_SPECIES_ID ( species ) = = SPECIES_GIRATINA & & itemId = = ITEM_GRISEOUS_ORB )
2018-09-30 12:27:51 +02:00
return FALSE ;
2021-08-12 20:44:53 +02:00
else if ( GET_BASE_SPECIES_ID ( species ) = = SPECIES_GENESECT & & holdEffect = = HOLD_EFFECT_DRIVE )
2018-09-30 12:27:51 +02:00
return FALSE ;
2021-08-12 20:44:53 +02:00
else if ( GET_BASE_SPECIES_ID ( species ) = = SPECIES_SILVALLY & & holdEffect = = HOLD_EFFECT_MEMORY )
2019-03-25 03:33:54 +01:00
return FALSE ;
2021-01-20 22:28:03 +01:00
else if ( GET_BASE_SPECIES_ID ( species ) = = SPECIES_ARCEUS & & holdEffect = = HOLD_EFFECT_PLATE )
2019-05-17 10:38:48 +02:00
return FALSE ;
2020-12-09 18:28:18 +01:00
# ifdef HOLD_EFFECT_Z_CRYSTAL
else if ( holdEffect = = HOLD_EFFECT_Z_CRYSTAL )
2019-05-17 10:38:48 +02:00
return FALSE ;
2020-12-09 18:28:18 +01:00
# endif
2018-09-30 12:27:51 +02:00
else
return TRUE ;
}
2019-08-08 13:06:55 +02:00
struct Pokemon * GetIllusionMonPtr ( u32 battlerId )
{
2020-06-28 19:45:48 +02:00
if ( gBattleStruct - > illusion [ battlerId ] . broken )
return NULL ;
if ( ! gBattleStruct - > illusion [ battlerId ] . set )
{
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
SetIllusionMon ( & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] , battlerId ) ;
else
SetIllusionMon ( & gEnemyParty [ gBattlerPartyIndexes [ battlerId ] ] , battlerId ) ;
}
if ( ! gBattleStruct - > illusion [ battlerId ] . on )
2019-08-08 13:06:55 +02:00
return NULL ;
return gBattleStruct - > illusion [ battlerId ] . mon ;
}
void ClearIllusionMon ( u32 battlerId )
{
2020-06-28 19:45:48 +02:00
memset ( & gBattleStruct - > illusion [ battlerId ] , 0 , sizeof ( gBattleStruct - > illusion [ battlerId ] ) ) ;
2019-08-08 13:06:55 +02:00
}
bool32 SetIllusionMon ( struct Pokemon * mon , u32 battlerId )
{
struct Pokemon * party , * partnerMon ;
s32 i , id ;
2020-06-28 19:45:48 +02:00
gBattleStruct - > illusion [ battlerId ] . set = 1 ;
2019-08-08 13:06:55 +02:00
if ( GetMonAbility ( mon ) ! = ABILITY_ILLUSION )
return FALSE ;
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
party = gPlayerParty ;
else
party = gEnemyParty ;
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerId ) ) )
partnerMon = & party [ gBattlerPartyIndexes [ BATTLE_PARTNER ( battlerId ) ] ] ;
else
partnerMon = mon ;
// Find last alive non-egg pokemon.
for ( i = PARTY_SIZE - 1 ; i > = 0 ; i - - )
{
2020-06-28 19:45:48 +02:00
id = i ;
2019-08-08 13:06:55 +02:00
if ( GetMonData ( & party [ id ] , MON_DATA_SANITY_HAS_SPECIES )
& & GetMonData ( & party [ id ] , MON_DATA_HP )
2021-09-22 05:20:34 +02:00
& & ! GetMonData ( & party [ id ] , MON_DATA_IS_EGG )
2019-08-08 13:06:55 +02:00
& & & party [ id ] ! = mon
& & & party [ id ] ! = partnerMon )
{
gBattleStruct - > illusion [ battlerId ] . on = 1 ;
gBattleStruct - > illusion [ battlerId ] . broken = 0 ;
gBattleStruct - > illusion [ battlerId ] . partyId = id ;
gBattleStruct - > illusion [ battlerId ] . mon = & party [ id ] ;
return TRUE ;
}
}
return FALSE ;
}
2020-10-15 05:16:50 +02:00
2020-10-21 20:30:20 +02:00
bool8 ShouldGetStatBadgeBoost ( u16 badgeFlag , u8 battlerId )
2020-10-21 16:44:03 +02:00
{
2020-10-21 20:01:53 +02:00
if ( B_BADGE_BOOST ! = GEN_3 )
return FALSE ;
2021-01-29 07:45:58 +01:00
else if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER ) )
2020-10-21 16:44:03 +02:00
return FALSE ;
else if ( GetBattlerSide ( battlerId ) ! = B_SIDE_PLAYER )
return FALSE ;
else if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER & & gTrainerBattleOpponent_A = = TRAINER_SECRET_BASE )
return FALSE ;
else if ( FlagGet ( badgeFlag ) )
return TRUE ;
else
return FALSE ;
}
2020-10-24 02:49:59 +02:00
2020-10-15 05:16:50 +02:00
u8 GetBattleMoveSplit ( u32 moveId )
{
2021-10-27 16:19:39 +02:00
if ( gSwapDamageCategory ) // Photon Geyser, Shell Side Arm, Light That Burns the Sky
2021-05-28 20:11:03 +02:00
return SPLIT_PHYSICAL ;
2021-06-06 01:38:37 +02:00
else if ( IS_MOVE_STATUS ( moveId ) | | B_PHYSICAL_SPECIAL_SPLIT > = GEN_4 )
2020-10-15 05:16:50 +02:00
return gBattleMoves [ moveId ] . split ;
else if ( gBattleMoves [ moveId ] . type < TYPE_MYSTERY )
return SPLIT_PHYSICAL ;
else
return SPLIT_SPECIAL ;
}
2021-01-05 23:44:12 +01:00
static bool32 TryRemoveScreens ( u8 battler )
{
bool32 removed = FALSE ;
u8 battlerSide = GetBattlerSide ( battler ) ;
u8 enemySide = GetBattlerSide ( BATTLE_OPPOSITE ( battler ) ) ;
2021-06-10 12:55:05 +02:00
2021-01-05 23:44:12 +01:00
// try to remove from battler's side
if ( gSideStatuses [ battlerSide ] & ( SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL ) )
{
gSideStatuses [ battlerSide ] & = ~ ( SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL ) ;
2021-02-02 17:00:07 +01:00
gSideTimers [ battlerSide ] . reflectTimer = 0 ;
gSideTimers [ battlerSide ] . lightscreenTimer = 0 ;
gSideTimers [ battlerSide ] . auroraVeilTimer = 0 ;
2021-01-05 23:44:12 +01:00
removed = TRUE ;
}
2021-06-10 12:55:05 +02:00
2021-01-05 23:44:12 +01:00
// try to remove from battler opponent's side
if ( gSideStatuses [ enemySide ] & ( SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL ) )
{
gSideStatuses [ enemySide ] & = ~ ( SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL ) ;
2021-02-02 17:00:07 +01:00
gSideTimers [ enemySide ] . reflectTimer = 0 ;
gSideTimers [ enemySide ] . lightscreenTimer = 0 ;
gSideTimers [ enemySide ] . auroraVeilTimer = 0 ;
2021-01-05 23:44:12 +01:00
removed = TRUE ;
}
2021-06-10 12:55:05 +02:00
2021-01-05 23:44:12 +01:00
return removed ;
}
2021-01-06 03:37:23 +01:00
static bool32 IsUnnerveAbilityOnOpposingSide ( u8 battlerId )
{
if ( IsAbilityOnOpposingSide ( battlerId , ABILITY_UNNERVE )
| | IsAbilityOnOpposingSide ( battlerId , ABILITY_AS_ONE_ICE_RIDER )
| | IsAbilityOnOpposingSide ( battlerId , ABILITY_AS_ONE_SHADOW_RIDER ) )
return TRUE ;
return FALSE ;
}
2021-03-29 01:29:22 +02:00
2020-12-13 23:02:21 +01:00
bool32 TestMoveFlags ( u16 move , u32 flag )
{
if ( gBattleMoves [ move ] . flags & flag )
return TRUE ;
return FALSE ;
}
struct Pokemon * GetBattlerPartyData ( u8 battlerId )
{
struct Pokemon * mon ;
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
mon = & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] ;
else
mon = & gEnemyParty [ gBattlerPartyIndexes [ battlerId ] ] ;
2021-06-10 12:55:05 +02:00
2020-12-13 23:02:21 +01:00
return mon ;
}
//Make sure the input bank is any bank on the specific mon's side
bool32 CanFling ( u8 battlerId )
{
u16 item = gBattleMons [ battlerId ] . item ;
u16 itemEffect = ItemId_GetHoldEffect ( item ) ;
if ( item = = ITEM_NONE
| | GetBattlerAbility ( battlerId ) = = ABILITY_KLUTZ
| | gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
| | gDisableStructs [ battlerId ] . embargoTimer ! = 0
| | ! CanBattlerGetOrLoseItem ( battlerId , item )
//|| itemEffect == HOLD_EFFECT_PRIMAL_ORB
| | itemEffect = = HOLD_EFFECT_GEMS
# ifdef ITEM_ABILITY_CAPSULE
| | item = = ITEM_ABILITY_CAPSULE
# endif
| | ( ItemId_GetPocket ( item ) = = POCKET_BERRIES & & IsAbilityOnSide ( battlerId , ABILITY_UNNERVE ) )
| | GetPocketByItemId ( item ) = = POCKET_POKE_BALLS )
return FALSE ;
return TRUE ;
}
// ability checks
bool32 IsRolePlayBannedAbilityAtk ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sRolePlayBannedAttackerAbilities ) ; i + + )
{
if ( ability = = sRolePlayBannedAttackerAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
bool32 IsRolePlayBannedAbility ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sRolePlayBannedAbilities ) ; i + + )
{
if ( ability = = sRolePlayBannedAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
bool32 IsSkillSwapBannedAbility ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sSkillSwapBannedAbilities ) ; i + + )
{
if ( ability = = sSkillSwapBannedAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
bool32 IsWorrySeedBannedAbility ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sWorrySeedBannedAbilities ) ; i + + )
{
if ( ability = = sWorrySeedBannedAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
bool32 IsGastroAcidBannedAbility ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sGastroAcidBannedAbilities ) ; i + + )
{
if ( ability = = sGastroAcidBannedAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
bool32 IsEntrainmentBannedAbilityAttacker ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sEntrainmentBannedAttackerAbilities ) ; i + + )
{
if ( ability = = sEntrainmentBannedAttackerAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility ( u16 ability )
{
u32 i ;
for ( i = 0 ; i < ARRAY_COUNT ( sEntrainmentTargetSimpleBeamBannedAbilities ) ; i + + )
{
if ( ability = = sEntrainmentTargetSimpleBeamBannedAbilities [ i ] )
return TRUE ;
}
return FALSE ;
}
2021-08-12 07:26:13 +02:00
2020-12-21 03:06:50 +01:00
// Sort an array of battlers by speed
// Useful for effects like pickpocket, eject button, red card, dancer
2020-11-13 07:30:00 +01:00
void SortBattlersBySpeed ( u8 * battlers , bool8 slowToFast )
{
2020-12-09 18:28:18 +01:00
int i , j , currSpeed , currBattler ;
u16 speeds [ 4 ] = { 0 } ;
2020-11-13 07:30:00 +01:00
2020-12-09 18:28:18 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
speeds [ i ] = GetBattlerTotalSpeedStat ( battlers [ i ] ) ;
for ( i = 1 ; i < gBattlersCount ; i + + )
{
currBattler = battlers [ i ] ;
currSpeed = speeds [ i ] ;
j = i - 1 ;
if ( slowToFast )
{
while ( j > = 0 & & speeds [ j ] > currSpeed )
{
battlers [ j + 1 ] = battlers [ j ] ;
speeds [ j + 1 ] = speeds [ j ] ;
j = j - 1 ;
}
}
else
{
while ( j > = 0 & & speeds [ j ] < currSpeed )
{
battlers [ j + 1 ] = battlers [ j ] ;
speeds [ j + 1 ] = speeds [ j ] ;
j = j - 1 ;
}
}
battlers [ j + 1 ] = currBattler ;
speeds [ j + 1 ] = currSpeed ;
}
2020-11-13 07:30:00 +01:00
}
2020-11-13 19:00:44 +01:00
void TryRestoreStolenItems ( void )
2020-11-13 07:30:00 +01:00
{
2020-11-13 19:00:44 +01:00
u32 i ;
u16 stolenItem = ITEM_NONE ;
2020-11-13 07:30:00 +01:00
2020-11-13 19:00:44 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2020-11-13 07:30:00 +01:00
{
2020-12-09 18:28:18 +01:00
if ( gBattleStruct - > itemStolen [ i ] . stolen )
{
stolenItem = gBattleStruct - > itemStolen [ i ] . originalItem ;
if ( stolenItem ! = ITEM_NONE & & ItemId_GetPocket ( stolenItem ) ! = POCKET_BERRIES )
2020-12-21 03:06:50 +01:00
SetMonData ( & gPlayerParty [ i ] , MON_DATA_HELD_ITEM , & stolenItem ) ; // Restore stolen non-berry items
2020-12-09 18:28:18 +01:00
}
2020-11-13 07:30:00 +01:00
}
}
2020-12-09 18:28:18 +01:00
bool32 CanStealItem ( u8 battlerStealing , u8 battlerItem , u16 item )
2020-11-13 21:42:49 +01:00
{
2020-12-09 18:28:18 +01:00
u8 stealerSide = GetBattlerSide ( battlerStealing ) ;
2020-11-13 21:42:49 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL )
return FALSE ;
2020-12-09 18:28:18 +01:00
2020-12-21 03:06:50 +01:00
// Check if the battler trying to steal should be able to
2020-12-09 18:28:18 +01:00
if ( stealerSide = = B_SIDE_OPPONENT
2020-11-13 21:42:49 +01:00
& & ! ( gBattleTypeFlags &
( BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
2021-08-12 07:26:13 +02:00
| BATTLE_TYPE_RECORDED_LINK
2020-11-13 21:42:49 +01:00
| BATTLE_TYPE_SECRET_BASE
2020-12-03 14:42:12 +01:00
# if B_TRAINERS_KNOCK_OFF_ITEMS
2020-11-13 21:42:49 +01:00
| BATTLE_TYPE_TRAINER
# endif
) ) )
{
return FALSE ;
}
else if ( ! ( gBattleTypeFlags &
( BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
2021-08-12 07:26:13 +02:00
| BATTLE_TYPE_RECORDED_LINK
2020-11-13 21:42:49 +01:00
| BATTLE_TYPE_SECRET_BASE ) )
2020-12-09 18:28:18 +01:00
& & ( gWishFutureKnock . knockedOffMons [ stealerSide ] & gBitTable [ gBattlerPartyIndexes [ battlerStealing ] ] ) )
2020-11-13 21:42:49 +01:00
{
return FALSE ;
}
2020-12-03 14:42:12 +01:00
2020-12-21 03:06:50 +01:00
if ( ! CanBattlerGetOrLoseItem ( battlerItem , item ) // Battler with item cannot have it stolen
| | ! CanBattlerGetOrLoseItem ( battlerStealing , item ) ) // Stealer cannot take the item
return FALSE ;
return TRUE ;
2020-11-13 21:42:49 +01:00
}
2020-12-09 18:28:18 +01:00
void TrySaveExchangedItem ( u8 battlerId , u16 stolenItem )
{
2020-12-21 03:06:50 +01:00
// Because BtlController_EmitSetMonData does SetMonData, we need to save the stolen item only if it matches the battler's original
// So, if the player steals an item during battle and has it stolen from it, it will not end the battle with it (naturally)
2020-12-09 18:28:18 +01:00
# if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
// If regular trainer battle and mon's original item matches what is being stolen, save it to be restored at end of battle
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER
& & ! ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER )
& & GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER
& & stolenItem = = gBattleStruct - > itemStolen [ gBattlerPartyIndexes [ battlerId ] ] . originalItem )
gBattleStruct - > itemStolen [ gBattlerPartyIndexes [ battlerId ] ] . stolen = TRUE ;
# endif
}
2021-08-12 07:26:13 +02:00
2021-09-02 21:33:42 +02:00
bool32 IsBattlerAffectedByHazards ( u8 battlerId , bool32 toxicSpikes )
{
bool32 ret = TRUE ;
u32 holdEffect = GetBattlerHoldEffect ( gActiveBattler , TRUE ) ;
if ( toxicSpikes & & holdEffect = = HOLD_EFFECT_HEAVY_DUTY_BOOTS & & ! IS_BATTLER_OF_TYPE ( battlerId , TYPE_POISON ) )
{
ret = FALSE ;
RecordItemEffectBattle ( battlerId , holdEffect ) ;
}
else if ( holdEffect = = HOLD_EFFECT_HEAVY_DUTY_BOOTS )
{
ret = FALSE ;
RecordItemEffectBattle ( battlerId , holdEffect ) ;
}
return ret ;
}
bool32 TestSheerForceFlag ( u8 battler , u16 move )
{
if ( GetBattlerAbility ( battler ) = = ABILITY_SHEER_FORCE & & gBattleMoves [ move ] . flags & FLAG_SHEER_FORCE_BOOST )
return TRUE ;
else
return FALSE ;
}
2021-09-03 18:17:38 +02:00
// This function is the body of "jumpifstat", but can be used dynamically in a function
2021-09-03 19:13:02 +02:00
bool32 CompareStat ( u8 battlerId , u8 statId , u8 cmpTo , u8 cmpKind )
2021-09-03 18:17:38 +02:00
{
bool8 ret = FALSE ;
u8 statValue = gBattleMons [ battlerId ] . statStages [ statId ] ;
// Because this command is used as a way of checking if a stat can be lowered/raised,
// we need to do some modification at run-time.
2021-09-03 19:13:02 +02:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_CONTRARY )
2021-09-03 18:17:38 +02:00
{
if ( cmpKind = = CMP_GREATER_THAN )
cmpKind = CMP_LESS_THAN ;
else if ( cmpKind = = CMP_LESS_THAN )
cmpKind = CMP_GREATER_THAN ;
if ( cmpTo = = MIN_STAT_STAGE )
cmpTo = MAX_STAT_STAGE ;
else if ( cmpTo = = MAX_STAT_STAGE )
cmpTo = MIN_STAT_STAGE ;
}
switch ( cmpKind )
{
case CMP_EQUAL :
if ( statValue = = cmpTo )
ret = TRUE ;
break ;
case CMP_NOT_EQUAL :
if ( statValue ! = cmpTo )
ret = TRUE ;
break ;
case CMP_GREATER_THAN :
if ( statValue > cmpTo )
ret = TRUE ;
break ;
case CMP_LESS_THAN :
if ( statValue < cmpTo )
ret = TRUE ;
break ;
case CMP_COMMON_BITS :
if ( statValue & cmpTo )
ret = TRUE ;
break ;
case CMP_NO_COMMON_BITS :
if ( ! ( statValue & cmpTo ) )
ret = TRUE ;
break ;
}
return ret ;
}
2021-09-14 18:50:36 +02:00
void BufferStatChange ( u8 battlerId , u8 statId , u8 stringId )
{
bool8 hasContrary = ( GetBattlerAbility ( battlerId ) = = ABILITY_CONTRARY ) ;
2021-09-16 23:10:41 +02:00
2021-09-14 18:50:36 +02:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , statId ) ;
if ( stringId = = STRINGID_STATFELL )
{
if ( hasContrary )
2021-09-16 23:10:41 +02:00
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , STRINGID_STATROSE )
2021-09-14 18:50:36 +02:00
else
2021-09-16 23:10:41 +02:00
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , STRINGID_STATFELL )
2021-09-14 18:50:36 +02:00
}
else if ( stringId = = STRINGID_STATROSE )
{
if ( hasContrary )
2021-09-16 23:10:41 +02:00
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , STRINGID_STATFELL )
2021-09-14 18:50:36 +02:00
else
2021-09-16 23:10:41 +02:00
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , STRINGID_STATROSE )
2021-09-14 18:50:36 +02:00
}
else
{
2021-09-16 23:10:41 +02:00
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , stringId )
2021-09-14 18:50:36 +02:00
}
}
bool32 TryRoomService ( u8 battlerId )
{
if ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM & & CompareStat ( battlerId , STAT_SPEED , MIN_STAT_STAGE , CMP_GREATER_THAN ) )
{
BufferStatChange ( battlerId , STAT_SPEED , STRINGID_STATFELL ) ;
gEffectBattler = gBattleScripting . battler = battlerId ;
SET_STATCHANGER ( STAT_SPEED , 1 , TRUE ) ;
gBattleScripting . animArg1 = 0xE + STAT_SPEED ;
gBattleScripting . animArg2 = 0 ;
gLastUsedItem = gBattleMons [ battlerId ] . item ;
return TRUE ;
}
else
{
return FALSE ;
}
}
2021-09-22 22:09:23 +02:00
2021-08-07 14:52:27 +02:00
void DoBurmyFormChange ( u32 monId )
2021-08-07 10:56:10 +02:00
{
u16 newSpecies , currSpecies ;
s32 sentIn ;
struct Pokemon * party = gPlayerParty ;
sentIn = gSentPokesToOpponent [ ( gBattlerFainted & 2 ) > > 1 ] ;
currSpecies = GetMonData ( & party [ monId ] , MON_DATA_SPECIES , NULL ) ;
2021-08-07 10:59:04 +02:00
if ( ( GET_BASE_SPECIES_ID ( currSpecies ) = = SPECIES_BURMY ) & & ( gBitTable [ monId ] & sentIn ) )
2021-08-07 10:56:10 +02:00
{
switch ( gBattleTerrain )
{
case BATTLE_TERRAIN_GRASS :
case BATTLE_TERRAIN_LONG_GRASS :
case BATTLE_TERRAIN_POND :
case BATTLE_TERRAIN_MOUNTAIN :
case BATTLE_TERRAIN_PLAIN :
newSpecies = SPECIES_BURMY ;
break ;
case BATTLE_TERRAIN_CAVE :
case BATTLE_TERRAIN_SAND :
newSpecies = SPECIES_BURMY_SANDY_CLOAK ;
break ;
case BATTLE_TERRAIN_BUILDING :
newSpecies = SPECIES_BURMY_TRASH_CLOAK ;
break ;
default : // Don't change form if last battle was water-related
newSpecies = SPECIES_NONE ;
break ;
}
if ( newSpecies ! = SPECIES_NONE )
{
SetMonData ( & party [ monId ] , MON_DATA_SPECIES , & newSpecies ) ;
CalculateMonStats ( & party [ monId ] ) ;
}
}
}
2021-09-22 22:26:09 +02:00
2021-10-11 01:54:17 +02:00
bool32 BlocksPrankster ( u16 move , u8 battlerPrankster , u8 battlerDef , bool32 checkTarget )
2021-09-22 22:09:23 +02:00
{
2021-09-23 20:35:37 +02:00
# if B_PRANKSTER_DARK_TYPES >= GEN_7
2021-10-11 01:54:17 +02:00
if ( ! gProtectStructs [ battlerPrankster ] . pranksterElevated )
2021-09-22 22:09:23 +02:00
return FALSE ;
2021-10-11 01:54:17 +02:00
if ( GetBattlerSide ( battlerPrankster ) = = GetBattlerSide ( battlerDef ) )
return FALSE ;
2021-11-24 00:09:54 +01:00
if ( checkTarget & & ( GetBattlerMoveTargetType ( battlerPrankster , move ) & ( MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS ) ) )
2021-10-11 01:54:17 +02:00
return FALSE ;
if ( ! IS_BATTLER_OF_TYPE ( battlerDef , TYPE_DARK ) )
2021-09-22 22:09:23 +02:00
return FALSE ;
2021-10-11 01:54:17 +02:00
if ( gStatuses3 [ battlerDef ] & STATUS3_SEMI_INVULNERABLE )
return FALSE ;
return TRUE ;
# endif
return FALSE ;
2021-09-22 22:09:23 +02:00
}
2021-10-28 23:52:52 +02:00
u16 GetUsedHeldItem ( u8 battler )
{
return gBattleStruct - > usedHeldItems [ gBattlerPartyIndexes [ battler ] ] [ GetBattlerSide ( battler ) ] ;
}
2021-10-30 04:33:50 +02:00
2021-05-24 17:52:45 +02:00
bool32 IsBattlerWeatherAffected ( u8 battlerId , u32 weatherFlags )
{
if ( ! WEATHER_HAS_EFFECT )
return FALSE ;
if ( gBattleWeather & weatherFlags )
{
// given weather is active -> check if its sun, rain against utility umbrella ( since only 1 weather can be active at once)
if ( gBattleWeather & ( WEATHER_SUN_ANY | WEATHER_RAIN_ANY ) & & GetBattlerHoldEffect ( battlerId , TRUE ) = = HOLD_EFFECT_UTILITY_UMBRELLA )
return FALSE ; // utility umbrella blocks sun, rain effects
return TRUE ;
}
return FALSE ;
}
2021-11-23 04:56:11 +01:00
// Gets move target before redirection effects etc. are applied
// Possible return values are defined in battle.h following MOVE_TARGET_SELECTED
2021-11-24 00:09:54 +01:00
u32 GetBattlerMoveTargetType ( u8 battlerId , u16 move )
2021-11-23 04:56:11 +01:00
{
u32 target ;
if ( gBattleMoves [ move ] . effect = = EFFECT_EXPANDING_FORCE
2021-11-24 00:09:54 +01:00
& & IsBattlerTerrainAffected ( battlerId , STATUS_FIELD_PSYCHIC_TERRAIN ) )
2021-11-23 04:56:11 +01:00
return MOVE_TARGET_BOTH ;
else
return gBattleMoves [ move ] . target ;
}