2017-09-17 14:10:32 +02:00
# include "global.h"
# include "battle.h"
2018-07-14 22:56:03 +02:00
# include "battle_interface.h"
2018-02-08 11:17:41 +01:00
# include "constants/battle_script_commands.h"
2017-12-05 18:55:48 +01:00
# include "constants/abilities.h"
2017-12-11 19:27:51 +01:00
# include "constants/moves.h"
2017-12-05 18:55:48 +01:00
# include "constants/hold_effects.h"
2017-12-31 16:28:57 +01:00
# include "constants/battle_anim.h"
2017-09-17 14:10:32 +02:00
# include "pokemon.h"
2017-12-11 19:27:51 +01:00
# include "constants/species.h"
2017-09-17 14:10:32 +02:00
# include "item.h"
2017-12-05 18:55:48 +01:00
# include "constants/items.h"
2017-09-17 14:10:32 +02:00
# include "util.h"
2017-12-05 18:55:48 +01:00
# include "constants/battle_move_effects.h"
2017-11-25 18:42:31 +01:00
# include "battle_scripts.h"
2017-12-05 19:27:33 +01:00
# include "random.h"
2017-09-17 14:10:32 +02:00
# include "text.h"
# include "string_util.h"
# include "battle_message.h"
2018-02-08 00:35:13 +01:00
# include "constants/battle_string_ids.h"
2017-09-28 17:38:07 +02:00
# include "battle_ai_script_commands.h"
2017-09-20 00:28:00 +02:00
# include "battle_controllers.h"
2017-09-17 17:14:32 +02:00
# include "event_data.h"
2017-10-06 17:06:45 +02:00
# include "link.h"
2017-11-27 21:24:34 +01:00
# include "berry.h"
2018-07-14 16:41:14 +02:00
# include "pokedex.h"
2018-07-27 23:40:10 +02:00
# include "constants/battle_config.h"
2017-09-17 14:10:32 +02:00
2017-09-17 15:19:15 +02:00
extern u8 weather_get_current ( void ) ;
2017-10-06 17:06:45 +02:00
2017-10-06 19:09:37 +02:00
// rom const data
static const u16 sSoundMovesTable [ ] =
{
MOVE_GROWL , MOVE_ROAR , MOVE_SING , MOVE_SUPERSONIC , MOVE_SCREECH , MOVE_SNORE ,
MOVE_UPROAR , MOVE_METAL_SOUND , MOVE_GRASS_WHISTLE , MOVE_HYPER_VOICE , 0xFFFF
} ;
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 ,
} ;
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 u16 sSpeedDiffToDmgTable [ ] =
{
40 , 60 , 80 , 120 , 150
} ;
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
{ 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
{ 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
{ 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
{ 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
{ 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
} ;
# 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 ;
}
return ret ;
}
2018-02-06 02:46:59 +01:00
void PressurePPLose ( u8 defender , u8 attacker , u16 move )
2017-10-06 17:06:45 +02:00
{
s32 i ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ defender ] . ability ! = ABILITY_PRESSURE )
2017-10-06 17:06:45 +02:00
return ;
for ( i = 0 ; i < 4 ; i + + )
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . moves [ i ] = = move )
2017-10-06 17:06:45 +02:00
break ;
}
if ( i = = 4 ) // mons don't share any moves
return ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . pp [ i ] ! = 0 )
gBattleMons [ attacker ] . pp [ i ] - - ;
2017-10-06 17:06:45 +02:00
2018-02-06 02:46:59 +01:00
if ( ! ( gBattleMons [ attacker ] . status2 & STATUS2_TRANSFORMED )
& & ! ( gDisableStructs [ attacker ] . unk18_b & gBitTable [ i ] ) )
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 + i , 0 , 1 , & gBattleMons [ gActiveBattler ] . pp [ i ] ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-06 17:06:45 +02:00
}
}
2018-02-06 02:46:59 +01:00
void PressurePPLoseOnUsingImprision ( u8 attacker )
2017-10-06 17:06:45 +02:00
{
s32 i , j ;
s32 imprisionPos = 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
{
2018-02-06 02:46:59 +01:00
if ( atkSide ! = GetBattlerSide ( i ) & & gBattleMons [ i ] . ability = = ABILITY_PRESSURE )
2017-10-06 17:06:45 +02:00
{
for ( j = 0 ; j < 4 ; j + + )
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ attacker ] . moves [ j ] = = MOVE_IMPRISON )
2017-10-06 17:06:45 +02:00
break ;
}
if ( j ! = 4 )
{
imprisionPos = 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
}
}
}
if ( imprisionPos ! = 4
2018-02-06 02:46:59 +01:00
& & ! ( gBattleMons [ attacker ] . status2 & STATUS2_TRANSFORMED )
& & ! ( gDisableStructs [ attacker ] . unk18_b & gBitTable [ imprisionPos ] ) )
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 + imprisionPos , 0 , 1 , & gBattleMons [ gActiveBattler ] . pp [ imprisionPos ] ) ;
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
{
s32 i , j ;
s32 perishSongPos = 4 ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-06 17:06:45 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ i ] . ability = = ABILITY_PRESSURE & & i ! = attacker )
2017-10-06 17:06:45 +02:00
{
for ( j = 0 ; j < 4 ; j + + )
{
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 ;
}
if ( j ! = 4 )
{
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
}
}
}
if ( perishSongPos ! = 4
2018-02-06 02:46:59 +01:00
& & ! ( gBattleMons [ attacker ] . status2 & STATUS2_TRANSFORMED )
& & ! ( gDisableStructs [ attacker ] . unk18_b & 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
{
s32 i ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
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 ] < < 0x1C ;
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-02-06 20:48:02 +01:00
void MarkBattlerForControllerExec ( u8 battlerId )
2017-10-06 17:06:45 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
2018-02-06 20:48:02 +01:00
gBattleControllerExecFlags | = gBitTable [ battlerId ] < < 0x1C ;
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
}
void sub_803F850 ( u8 arg0 )
{
s32 i ;
2017-10-13 17:09:36 +02:00
for ( i = 0 ; i < GetLinkPlayerCount ( ) ; i + + )
2018-02-06 20:48:02 +01:00
gBattleControllerExecFlags | = gBitTable [ arg0 ] < < ( i < < 2 ) ;
2017-10-06 17:06:45 +02:00
2018-02-06 20:48:02 +01:00
gBattleControllerExecFlags & = ~ ( 0x10000000 < < arg0 ) ;
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-02-06 02:46:59 +01:00
gDisableStructs [ battler ] . rolloutCounter1 = 0 ;
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
| | gProtectStructs [ battler ] . targetNotAffected
| | gProtectStructs [ battler ] . usedImprisionedMove
| | gProtectStructs [ battler ] . loveImmobility
| | gProtectStructs [ battler ] . usedDisabledMove
| | gProtectStructs [ battler ] . usedTauntedMove
| | gProtectStructs [ battler ] . flag2Unknown
| | gProtectStructs [ battler ] . flinchImmobility
| | gProtectStructs [ battler ] . confusionSelfDmg )
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
{
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
}
2018-02-06 02:46:59 +01:00
void sub_803F9EC ( 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
}
}
2018-02-06 02:46:59 +01:00
void sub_803FA70 ( 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
{
2018-02-06 02:46:59 +01:00
sub_803F9EC ( 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
}
2017-10-03 21:35:27 +02:00
u8 TrySetCantSelectMoveBattleScript ( void )
2017-09-17 14:10:32 +02:00
{
u8 limitations = 0 ;
2018-02-06 02:46:59 +01:00
u16 move = gBattleMons [ gActiveBattler ] . moves [ gBattleBufferB [ gActiveBattler ] [ 2 ] ] ;
2017-09-17 14:10:32 +02:00
u8 holdEffect ;
2018-02-06 02:46:59 +01:00
u16 * choicedMove = & gBattleStruct - > choicedMove [ gActiveBattler ] ;
2017-09-17 14:10:32 +02:00
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . disabledMove = = move & & move ! = 0 )
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 ;
gProtectStructs [ gActiveBattler ] . flag_x10 = 1 ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingDisabledMove ;
2017-09-17 14:10:32 +02:00
limitations = 1 ;
}
}
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 ;
gProtectStructs [ gActiveBattler ] . flag_x10 = 1 ;
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-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . tauntTimer1 ! = 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 ;
gProtectStructs [ gActiveBattler ] . flag_x10 = 1 ;
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 + + ;
}
}
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 )
{
2018-02-06 02:46:59 +01:00
gPalaceSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingImprisionedMoveInPalace ;
gProtectStructs [ gActiveBattler ] . flag_x10 = 1 ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_SelectingImprisionedMove ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . item = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ gActiveBattler ] . holdEffect ;
2017-09-17 14:10:32 +02:00
else
2018-02-06 02:46:59 +01:00
holdEffect = ItemId_GetHoldEffect ( gBattleMons [ gActiveBattler ] . item ) ;
2017-09-17 14:10:32 +02:00
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = gActiveBattler ;
2017-09-17 14:10:32 +02:00
if ( holdEffect = = HOLD_EFFECT_CHOICE_BAND & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = move )
{
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 )
{
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . flag_x10 = 1 ;
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 + + ;
}
}
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . pp [ gBattleBufferB [ gActiveBattler ] [ 2 ] ] = = 0 )
2017-09-17 14:10:32 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . flag_x10 = 1 ;
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
{
u8 holdEffect ;
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 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . item = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ battlerId ] . holdEffect ;
2017-09-17 14:10:32 +02:00
else
2018-02-08 11:17:41 +01:00
holdEffect = ItemId_GetHoldEffect ( gBattleMons [ battlerId ] . item ) ;
2017-09-17 14:10:32 +02:00
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = battlerId ;
2017-09-17 14:10:32 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; 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-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . pp [ i ] = = 0 & & check & MOVE_LIMITATION_PP )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . moves [ i ] = = gDisableStructs [ battlerId ] . disabledMove & & check & MOVE_LIMITATION_DISABLED )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . moves [ i ] = = gLastMoves [ battlerId ] & & check & MOVE_LIMITATION_TORMENTED & & gBattleMons [ battlerId ] . status2 & STATUS2_TORMENT )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-02-08 11:17:41 +01:00
if ( gDisableStructs [ battlerId ] . tauntTimer1 & & check & MOVE_LIMITATION_TAUNT & & gBattleMoves [ gBattleMons [ battlerId ] . moves [ i ] ] . power = = 0 )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-02-08 11:17:41 +01:00
if ( GetImprisonedMovesCount ( battlerId , gBattleMons [ battlerId ] . moves [ i ] ) & & check & MOVE_LIMITATION_IMPRISION )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-02-08 11:17:41 +01:00
if ( gDisableStructs [ battlerId ] . encoreTimer1 & & gDisableStructs [ battlerId ] . encoredMove ! = gBattleMons [ battlerId ] . moves [ i ] )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
2018-02-08 11:17:41 +01:00
if ( holdEffect = = HOLD_EFFECT_CHOICE_BAND & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = gBattleMons [ battlerId ] . moves [ i ] )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
}
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
{
2018-07-07 19:57:09 +02:00
gProtectStructs [ gActiveBattler ] . noValidMoves = 1 ;
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_NoMovesLeft ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-07-07 19:57:09 +02:00
gProtectStructs [ gActiveBattler ] . noValidMoves = 0 ;
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 ;
u8 imprisionedMoves = 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 ;
for ( j = 0 ; j < 4 ; j + + )
{
if ( move = = gBattleMons [ i ] . moves [ j ] )
break ;
}
if ( j < 4 )
imprisionedMoves + + ;
}
}
return imprisionedMoves ;
}
2018-07-21 12:10:08 +02:00
enum
{
ENDTURN_ORDER ,
ENDTURN_REFLECT ,
ENDTURN_LIGHT_SCREEN ,
2018-07-21 12:56:07 +02:00
ENDTURN_AURORA_VEIL ,
2018-07-21 12:10:08 +02:00
ENDTURN_MIST ,
2018-07-21 12:56:07 +02:00
ENDTURN_LUCKY_CHANT ,
2018-07-21 12:10:08 +02:00
ENDTURN_SAFEGUARD ,
2018-07-21 12:56:07 +02:00
ENDTURN_TAILWIND ,
2018-07-21 12:10:08 +02:00
ENDTURN_WISH ,
ENDTURN_RAIN ,
ENDTURN_SANDSTORM ,
ENDTURN_SUN ,
ENDTURN_HAIL ,
2018-07-21 16:34:43 +02:00
ENDTURN_GRAVITY ,
2018-07-21 13:24:20 +02:00
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 ,
2018-07-21 12:10:08 +02:00
ENDTURN_FIELD_COUNT ,
} ;
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-07-21 12:10:08 +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 + + ;
gBattleStruct - > turnEffectsSide = 0 ;
2017-09-17 14:10:32 +02:00
// fall through
2018-07-21 12:10:08 +02:00
case ENDTURN_REFLECT :
while ( gBattleStruct - > turnEffectsSide < 2 )
2017-09-17 14:10:32 +02:00
{
2018-07-21 12:10:08 +02:00
side = gBattleStruct - > turnEffectsSide ;
2018-07-01 11:15:42 +02:00
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 + + ;
}
}
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide + + ;
2017-09-17 14:10:32 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide = 0 ;
2017-09-17 14:10:32 +02:00
}
break ;
2018-07-21 12:10:08 +02:00
case ENDTURN_LIGHT_SCREEN :
while ( gBattleStruct - > turnEffectsSide < 2 )
2017-09-17 14:10:32 +02:00
{
2018-07-21 12:10:08 +02:00
side = gBattleStruct - > turnEffectsSide ;
2018-07-01 11:15:42 +02:00
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 + + ;
}
}
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide + + ;
2017-09-17 14:10:32 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide = 0 ;
2017-09-17 14:10:32 +02:00
}
break ;
2018-07-21 12:56:07 +02:00
case ENDTURN_AURORA_VEIL :
while ( gBattleStruct - > turnEffectsSide < 2 )
{
side = gBattleStruct - > turnEffectsSide ;
gActiveBattler = gBattlerAttacker = gSideTimers [ side ] . auroraVeilBattlerId ;
if ( gSideStatuses [ side ] & SIDE_STATUS_AURORA_VEIL )
{
if ( - - gSideTimers [ side ] . auroraVeilTimer = = 0 )
{
gSideStatuses [ side ] & = ~ SIDE_STATUS_AURORA_VEIL ;
BattleScriptExecute ( BattleScript_AuroraVeilEnds ) ;
effect + + ;
}
}
gBattleStruct - > turnEffectsSide + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turnCountersTracker + + ;
gBattleStruct - > turnEffectsSide = 0 ;
}
break ;
2018-07-21 12:10:08 +02:00
case ENDTURN_MIST :
while ( gBattleStruct - > turnEffectsSide < 2 )
2017-09-17 14:10:32 +02:00
{
2018-07-21 12:10:08 +02:00
side = gBattleStruct - > turnEffectsSide ;
2018-07-01 11:15:42 +02:00
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 + + ;
}
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide + + ;
2017-09-17 14:10:32 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide = 0 ;
2017-09-17 14:10:32 +02:00
}
break ;
2018-07-21 12:10:08 +02:00
case ENDTURN_SAFEGUARD :
while ( gBattleStruct - > turnEffectsSide < 2 )
2017-09-17 14:10:32 +02:00
{
2018-07-21 12:10:08 +02:00
side = gBattleStruct - > turnEffectsSide ;
2018-07-01 11:15:42 +02:00
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 + + ;
}
}
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide + + ;
2017-09-17 14:10:32 +02:00
if ( effect )
break ;
}
if ( ! effect )
{
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker + + ;
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide = 0 ;
2017-09-17 14:10:32 +02:00
}
break ;
2018-07-21 12:56:07 +02:00
case ENDTURN_LUCKY_CHANT :
while ( gBattleStruct - > turnEffectsSide < 2 )
{
side = gBattleStruct - > turnEffectsSide ;
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 + + ;
}
}
gBattleStruct - > turnEffectsSide + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turnCountersTracker + + ;
gBattleStruct - > turnEffectsSide = 0 ;
}
break ;
case ENDTURN_TAILWIND :
while ( gBattleStruct - > turnEffectsSide < 2 )
{
side = gBattleStruct - > turnEffectsSide ;
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 + + ;
}
}
gBattleStruct - > turnEffectsSide + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turnCountersTracker + + ;
gBattleStruct - > turnEffectsSide = 0 ;
}
break ;
2018-07-21 12:10:08 +02:00
case ENDTURN_WISH :
while ( gBattleStruct - > turnEffectsSide < gBattlersCount )
2017-09-17 14:10:32 +02:00
{
2018-07-21 12:10:08 +02:00
gActiveBattler = gBattlerByTurnOrder [ gBattleStruct - > turnEffectsSide ] ;
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 + + ;
}
2018-07-21 12:10:08 +02:00
gBattleStruct - > turnEffectsSide + + ;
2017-09-17 14:10:32 +02:00
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-07-21 12:10:08 +02:00
case ENDTURN_RAIN :
2017-09-17 14:10:32 +02:00
if ( gBattleWeather & WEATHER_RAIN_ANY )
{
if ( ! ( gBattleWeather & WEATHER_RAIN_PERMANENT ) )
{
if ( - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_RAIN_TEMPORARY ;
gBattleWeather & = ~ WEATHER_RAIN_DOWNPOUR ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 2 ;
}
else if ( gBattleWeather & WEATHER_RAIN_DOWNPOUR )
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
else
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
}
else if ( gBattleWeather & WEATHER_RAIN_DOWNPOUR )
2017-11-26 17:15:28 +01:00
{
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
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
{
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
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-07-21 12:10:08 +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 ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
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 12:10:08 +02:00
case ENDTURN_SUN :
2017-09-17 14:10:32 +02:00
if ( gBattleWeather & WEATHER_SUN_ANY )
{
if ( ! ( gBattleWeather & WEATHER_SUN_PERMANENT ) & & - - gWishFutureKnock . weatherDuration = = 0 )
{
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-07-21 12:10:08 +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 ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
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 + + ;
break ;
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 :
if ( gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN & & - - gFieldTimers . electricTerrainTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_ELECTRIC_TERRAIN ) ;
BattleScriptExecute ( BattleScript_ElectricTerrainEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_MISTY_TERRAIN :
if ( gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN & & - - gFieldTimers . mistyTerrainTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_MISTY_TERRAIN ) ;
BattleScriptExecute ( BattleScript_MistyTerrainEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_GRASSY_TERRAIN :
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & - - gFieldTimers . grassyTerrainTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_GRASSY_TERRAIN ) ;
BattleScriptExecute ( BattleScript_GrassyTerrainEnds ) ;
effect + + ;
}
gBattleStruct - > turnCountersTracker + + ;
break ;
case ENDTURN_PSYCHIC_TERRAIN :
if ( gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN & & - - gFieldTimers . psychicTerrainTimer = = 0 )
{
gFieldStatuses & = ~ ( STATUS_FIELD_PSYCHIC_TERRAIN ) ;
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-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 ,
ENDTURN_ITEMS1 ,
ENDTURN_LEECH_SEED ,
ENDTURN_POISON ,
ENDTURN_BAD_POISON ,
ENDTURN_BURN ,
ENDTURN_NIGHTMARES ,
ENDTURN_CURSE ,
ENDTURN_WRAP ,
ENDTURN_UPROAR ,
ENDTURN_THRASH ,
ENDTURN_DISABLE ,
ENDTURN_ENCORE ,
ENDTURN_MAGNET_RISE ,
ENDTURN_TELEKINESIS ,
ENDTURN_HEALBLOCK ,
ENDTURN_EMBARGO ,
ENDTURN_LOCK_ON ,
ENDTURN_CHARGE ,
2018-07-23 21:36:05 +02:00
ENDTURN_LASER_FOCUS ,
2018-07-18 22:07:48 +02:00
ENDTURN_TAUNT ,
ENDTURN_YAWN ,
ENDTURN_ITEMS2 ,
2018-07-19 21:18:20 +02:00
ENDTURN_ROOST ,
2018-07-18 22:07:48 +02:00
ENDTURN_BATTLER_COUNT
} ;
2017-09-17 14:10:32 +02:00
2018-07-18 22:07:48 +02:00
u8 DoBattlerEndTurnEffects ( void )
2017-09-17 14:10:32 +02:00
{
2018-07-18 22:07:48 +02:00
u8 effect = FALSE ;
2017-09-17 14:10:32 +02:00
gHitMarker | = ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
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 + + ;
2017-09-17 14:10:32 +02:00
}
else
{
2018-07-22 18:40:18 +02:00
u8 ability = GetBattlerAbility ( gActiveBattler ) ;
2017-09-17 14:10:32 +02:00
switch ( gBattleStruct - > turnEffectsTracker )
{
2018-07-18 22:07:48 +02:00
case ENDTURN_INGRAIN : // ingrain
2018-02-06 02:46:59 +01:00
if ( ( gStatuses3 [ gActiveBattler ] & STATUS3_ROOTED )
2018-07-18 22:07:48 +02:00
& & ! BATTLER_MAX_HP ( gActiveBattler )
& & ! ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK )
2018-02-06 02:46:59 +01:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
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 ;
gBattleMoveDamage * = - 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_IngrainTurnHeal ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
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 )
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
BattleScriptExecute ( BattleScript_AquaRingHeal ) ;
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_ABILITIES : // end turn abilities
2018-02-06 02:46:59 +01:00
if ( AbilityBattleEffects ( ABILITYEFFECT_ENDTURN , gActiveBattler , 0 , 0 , 0 ) )
2017-09-17 14:10:32 +02:00
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_ITEMS1 : // item effects
2018-02-06 02:46:59 +01:00
if ( ItemBattleEffects ( 1 , gActiveBattler , 0 ) )
2017-09-17 14:10:32 +02:00
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_ITEMS2 : // item effects again
2018-02-06 02:46:59 +01:00
if ( ItemBattleEffects ( 1 , gActiveBattler , 1 ) )
2017-09-17 14:10:32 +02:00
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_LEECH_SEED : // leech seed
2018-02-06 02:46:59 +01:00
if ( ( gStatuses3 [ gActiveBattler ] & STATUS3_LEECHSEED )
2018-07-01 11:15:42 +02:00
& & gBattleMons [ gStatuses3 [ gActiveBattler ] & STATUS3_LEECHSEED_BATTLER ] . hp ! = 0
2018-02-06 02:46:59 +01:00
& & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
gBattlerTarget = gStatuses3 [ gActiveBattler ] & STATUS3_LEECHSEED_BATTLER ; // Notice gBattlerTarget is actually the HP receiver.
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 ;
2018-02-06 23:09:39 +01:00
gBattleScripting . animArg1 = gBattlerTarget ;
gBattleScripting . animArg2 = gBattlerAttacker ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_LeechSeedTurnDrain ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_POISON : // poison
2018-07-22 18:40:18 +02:00
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_POISON )
& & gBattleMons [ gActiveBattler ] . hp ! = 0
& & ability ! = ABILITY_MAGIC_GUARD )
2017-09-17 14:10:32 +02:00
{
2018-07-22 18:40:18 +02:00
if ( ability = = ABILITY_POISON_HEAL )
{
if ( ! BATTLER_MAX_HP ( gActiveBattler ) )
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
BattleScriptExecute ( BattleScript_PoisonHealActivates ) ;
effect + + ;
}
}
else
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptExecute ( BattleScript_PoisonTurnDmg ) ;
effect + + ;
}
2017-09-17 14:10:32 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_BAD_POISON : // toxic poison
2018-07-22 18:40:18 +02:00
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_TOXIC_POISON )
& & gBattleMons [ gActiveBattler ] . hp ! = 0
& & ability ! = ABILITY_MAGIC_GUARD )
2017-09-17 14:10:32 +02:00
{
2018-07-22 18:40:18 +02:00
if ( ability = = ABILITY_POISON_HEAL )
{
if ( ! BATTLER_MAX_HP ( gActiveBattler ) )
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
BattleScriptExecute ( BattleScript_PoisonHealActivates ) ;
effect + + ;
}
}
else
{
gBattleMoveDamage = gBattleMons [ gActiveBattler ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_TOXIC_COUNTER ) ! = STATUS1_TOXIC_COUNTER ) // not 16 turns
gBattleMons [ gActiveBattler ] . status1 + = 0x100 ;
gBattleMoveDamage * = ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_TOXIC_COUNTER ) > > 8 ;
BattleScriptExecute ( BattleScript_PoisonTurnDmg ) ;
effect + + ;
}
2017-09-17 14:10:32 +02:00
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_BURN : // burn
2018-07-22 18:40:18 +02:00
if ( ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_BURN )
& & gBattleMons [ gActiveBattler ] . hp ! = 0
& & ability ! = ABILITY_MAGIC_GUARD )
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 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BurnTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_NIGHTMARES : // spooky nightmares
2018-07-22 18:40:18 +02:00
if ( ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_NIGHTMARE )
& & gBattleMons [ gActiveBattler ] . hp ! = 0
& & ability ! = ABILITY_MAGIC_GUARD )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +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.
2018-02-06 02:46:59 +01:00
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 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_NightmareTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
else
{
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 & = ~ STATUS2_NIGHTMARE ;
2017-09-17 14:10:32 +02:00
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_CURSE : // curse
2018-07-22 18:40:18 +02:00
if ( ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_CURSED )
& & gBattleMons [ gActiveBattler ] . hp ! = 0
& & ability ! = ABILITY_MAGIC_GUARD )
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 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_CurseTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_WRAP : // wrap
2018-02-06 02:46:59 +01:00
if ( ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_WRAPPED ) & & gBattleMons [ gActiveBattler ] . hp ! = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 - = 0x2000 ;
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_WRAPPED ) // damaged by wrap
2017-09-17 14:10:32 +02:00
{
// This is the only way I could get this array access to match.
2018-02-06 02:46:59 +01:00
gBattleScripting . animArg1 = * ( gBattleStruct - > wrappedMove + gActiveBattler * 2 + 0 ) ;
gBattleScripting . animArg2 = * ( gBattleStruct - > wrappedMove + gActiveBattler * 2 + 1 ) ;
2017-11-26 13:26:58 +01:00
gBattleTextBuff1 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff1 [ 1 ] = B_BUFF_MOVE ;
2018-02-06 02:46:59 +01:00
gBattleTextBuff1 [ 2 ] = * ( gBattleStruct - > wrappedMove + gActiveBattler * 2 + 0 ) ;
gBattleTextBuff1 [ 3 ] = * ( gBattleStruct - > wrappedMove + gActiveBattler * 2 + 1 ) ;
2017-09-17 14:10:32 +02:00
gBattleTextBuff1 [ 4 ] = EOS ;
gBattlescriptCurrInstr = BattleScript_WrapTurnDmg ;
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 ;
}
else // broke free
{
2017-11-26 13:26:58 +01:00
gBattleTextBuff1 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff1 [ 1 ] = B_BUFF_MOVE ;
2018-02-06 02:46:59 +01:00
gBattleTextBuff1 [ 2 ] = * ( gBattleStruct - > wrappedMove + gActiveBattler * 2 + 0 ) ;
gBattleTextBuff1 [ 3 ] = * ( gBattleStruct - > wrappedMove + gActiveBattler * 2 + 1 ) ;
2017-09-17 14:10:32 +02:00
gBattleTextBuff1 [ 4 ] = EOS ;
gBattlescriptCurrInstr = BattleScript_WrapEnds ;
}
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_UPROAR : // uproar
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_UPROAR )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
for ( gBattlerAttacker = 0 ; gBattlerAttacker < gBattlersCount ; gBattlerAttacker + + )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
if ( ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_SLEEP )
& & gBattleMons [ gBattlerAttacker ] . ability ! = ABILITY_SOUNDPROOF )
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-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_MonWokeUpInUproar ) ;
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
break ;
}
}
2018-02-06 23:09:39 +01:00
if ( gBattlerAttacker ! = gBattlersCount )
2017-09-17 14:10:32 +02:00
{
effect = 2 ; // a pokemon was awaken
break ;
}
else
{
2018-02-06 23:09:39 +01:00
gBattlerAttacker = gActiveBattler ;
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 - = 0x10 ; // uproar timer goes down
if ( WasUnableToUseMove ( gActiveBattler ) )
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
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
}
2018-02-06 02:46:59 +01:00
else if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_UPROAR )
2017-09-17 14:10:32 +02:00
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 | = STATUS2_MULTIPLETURNS ;
2017-09-17 14:10:32 +02:00
}
else
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2018-02-06 02:46:59 +01:00
CancelMultiTurnMoves ( gActiveBattler ) ;
2017-09-17 14:10:32 +02:00
}
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_PrintUproarOverTurns ) ;
2017-09-17 14:10:32 +02:00
effect = 1 ;
}
}
if ( effect ! = 2 )
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_THRASH : // thrash
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_LOCK_CONFUSE )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 - = 0x400 ;
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
{
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_MULTIPLETURNS ) ;
if ( ! ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_CONFUSION ) )
2017-09-17 14:10:32 +02:00
{
2017-11-26 13:26:58 +01:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER ;
2017-09-17 14:10:32 +02:00
SetMoveEffect ( 1 , 0 ) ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_CONFUSION )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ThrashConfuses ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_DISABLE : // disable
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . disableTimer1 ! = 0 )
2017-09-17 14:10:32 +02:00
{
2018-07-01 11:15:42 +02:00
s32 i ;
2017-09-17 14:10:32 +02:00
for ( i = 0 ; i < 4 ; i + + )
{
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . disabledMove = = gBattleMons [ gActiveBattler ] . moves [ i ] )
2017-09-17 14:10:32 +02:00
break ;
}
if ( i = = 4 ) // pokemon does not have the disabled move anymore
{
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . disabledMove = 0 ;
gDisableStructs [ gActiveBattler ] . disableTimer1 = 0 ;
2017-09-17 14:10:32 +02:00
}
2018-02-06 02:46:59 +01:00
else if ( - - gDisableStructs [ gActiveBattler ] . disableTimer1 = = 0 ) // disable ends
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . disabledMove = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_DisabledNoMore ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_ENCORE : // encore
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . encoreTimer1 ! = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . moves [ gDisableStructs [ gActiveBattler ] . encoredMovePos ] ! = gDisableStructs [ gActiveBattler ] . encoredMove ) // pokemon does not have the encored move anymore
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . encoredMove = 0 ;
gDisableStructs [ gActiveBattler ] . encoreTimer1 = 0 ;
2017-09-17 14:10:32 +02:00
}
2018-02-06 02:46:59 +01:00
else if ( - - gDisableStructs [ gActiveBattler ] . encoreTimer1 = = 0
| | gBattleMons [ gActiveBattler ] . pp [ gDisableStructs [ gActiveBattler ] . encoredMovePos ] = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . encoredMove = 0 ;
gDisableStructs [ gActiveBattler ] . encoreTimer1 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_EncoredNoMore ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_LOCK_ON : // lock-on decrement
2018-02-06 02:46:59 +01:00
if ( gStatuses3 [ gActiveBattler ] & STATUS3_ALWAYS_HITS )
gStatuses3 [ gActiveBattler ] - = 0x8 ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_CHARGE : // charge
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . chargeTimer1 & & - - gDisableStructs [ gActiveBattler ] . chargeTimer1 = = 0 )
gStatuses3 [ gActiveBattler ] & = ~ STATUS3_CHARGED_UP ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_TAUNT : // taunt
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . tauntTimer1 )
gDisableStructs [ gActiveBattler ] . tauntTimer1 - - ;
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_YAWN : // yawn
2018-02-06 02:46:59 +01:00
if ( gStatuses3 [ gActiveBattler ] & STATUS3_YAWN )
{
gStatuses3 [ gActiveBattler ] - = 0x800 ;
if ( ! ( gStatuses3 [ gActiveBattler ] & STATUS3_YAWN ) & & ! ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_ANY )
& & gBattleMons [ gActiveBattler ] . ability ! = ABILITY_VITAL_SPIRIT
& & gBattleMons [ gActiveBattler ] . ability ! = ABILITY_INSOMNIA & & ! UproarWakeUpCheck ( gActiveBattler ) )
{
CancelMultiTurnMoves ( gActiveBattler ) ;
gBattleMons [ gActiveBattler ] . status1 | = ( Random ( ) & 3 ) + 2 ;
2018-02-06 20:48:02 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2018-02-08 11:17:41 +01:00
gEffectBattler = gActiveBattler ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_YawnMakesAsleep ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-23 21:36:05 +02:00
case ENDTURN_LASER_FOCUS :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_LASER_FOCUS )
{
if ( gDisableStructs [ gActiveBattler ] . laserFocusTimer ! = 0 )
gDisableStructs [ gActiveBattler ] . laserFocusTimer - - ;
if ( gDisableStructs [ gActiveBattler ] . laserFocusTimer = = 0 )
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_LASER_FOCUS ) ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-18 22:07:48 +02:00
case ENDTURN_EMBARGO :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_EMBARGO )
{
if ( gDisableStructs [ gActiveBattler ] . embargoTimer ! = 0 )
gDisableStructs [ gActiveBattler ] . embargoTimer - - ;
if ( gDisableStructs [ gActiveBattler ] . embargoTimer = = 0 )
{
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_EMBARGO ) ;
BattleScriptExecute ( BattleScript_EmbargoEndTurn ) ;
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_MAGNET_RISE :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_MAGNET_RISE )
{
if ( gDisableStructs [ gActiveBattler ] . magnetRiseTimer ! = 0 )
gDisableStructs [ gActiveBattler ] . magnetRiseTimer - - ;
if ( gDisableStructs [ gActiveBattler ] . magnetRiseTimer = = 0 )
{
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_MAGNET_RISE ) ;
BattleScriptExecute ( BattleScript_MagnetRiseEndTurn ) ;
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_TELEKINESIS :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_TELEKINESIS )
{
if ( gDisableStructs [ gActiveBattler ] . telekinesisTimer ! = 0 )
gDisableStructs [ gActiveBattler ] . telekinesisTimer - - ;
if ( gDisableStructs [ gActiveBattler ] . telekinesisTimer = = 0 )
{
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_TELEKINESIS ) ;
BattleScriptExecute ( BattleScript_TelekinesisEndTurn ) ;
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case ENDTURN_HEALBLOCK :
if ( gStatuses3 [ gActiveBattler ] & STATUS3_HEAL_BLOCK )
{
if ( gDisableStructs [ gActiveBattler ] . healBlockTimer ! = 0 )
gDisableStructs [ gActiveBattler ] . healBlockTimer - - ;
if ( gDisableStructs [ gActiveBattler ] . healBlockTimer = = 0 )
{
gStatuses3 [ gActiveBattler ] & = ~ ( STATUS3_HEAL_BLOCK ) ;
BattleScriptExecute ( BattleScript_HealBlockEndTurn ) ;
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
2018-07-19 21:18:20 +02:00
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 ;
2018-07-18 22:07:48 +02:00
case ENDTURN_BATTLER_COUNT : // done
2017-09-17 14:10:32 +02:00
gBattleStruct - > turnEffectsTracker = 0 ;
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnEffectsBattlerId + + ;
2017-09-17 14:10:32 +02:00
break ;
}
if ( effect ! = 0 )
return effect ;
}
}
gHitMarker & = ~ ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
return 0 ;
}
2017-12-02 14:08:55 +01:00
bool8 HandleWishPerishSongOnTurnEnd ( void )
2017-09-17 14:10:32 +02:00
{
gHitMarker | = ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
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 )
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
else
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
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-06 02:46:59 +01:00
gBattleMoveDamage = gWishFutureKnock . futureSightDmg [ gActiveBattler ] ;
2018-02-07 22:53:40 +01:00
gSpecialStatuses [ gBattlerTarget ] . dmg = 0xFFFF ;
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
}
}
// Why do I have to keep doing this to match?
{
2017-12-02 14:08:55 +01:00
u8 * state = & gBattleStruct - > wishPerishSongState ;
* state = 1 ;
2018-02-07 22:53:40 +01:00
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-02-06 02:46:59 +01:00
PREPARE_BYTE_NUMBER_BUFFER ( gBattleTextBuff1 , 1 , gDisableStructs [ gActiveBattler ] . perishSongTimer1 ) ;
if ( gDisableStructs [ gActiveBattler ] . perishSongTimer1 = = 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-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . perishSongTimer1 - - ;
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 )
2017-09-17 15:19:15 +02:00
& & gBattleStruct - > field_DA = = 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 ) ;
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB8F3 ;
BattleScriptExecute ( BattleScript_82DB8F3 ) ;
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 ;
}
gHitMarker & = ~ ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
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
{
2018-07-01 11:15:42 +02:00
if ( gAbsentBattlerFlags & gBitTable [ i ] & & ! HasNoMonsToSwitch ( i , 6 , 6 ) )
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
& & ! ( gBattleStruct - > field_DF & gBitTable [ gBattlerPartyIndexes [ gBattleStruct - > faintedActionsBattlerId ] ] )
& & ! ( 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 :
2018-02-08 11:17:41 +01:00
sub_803F9EC ( 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 ;
2017-09-17 14:10:32 +02:00
break ;
case 3 :
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 :
2017-09-17 15:19:15 +02:00
if ( AbilityBattleEffects ( ABILITYEFFECT_INTIMIDATE1 , 0 , 0 , 0 , 0 ) | | AbilityBattleEffects ( ABILITYEFFECT_TRACE , 0 , 0 , 0 , 0 ) | | ItemBattleEffects ( 1 , 0 , 1 ) | | AbilityBattleEffects ( ABILITYEFFECT_FORECAST , 0 , 0 , 0 , 0 ) )
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 ;
}
2017-10-06 00:12:01 +02:00
void TryClearRageStatuses ( 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 ) ;
}
}
# define ATKCANCELLER_MAX_CASE 14
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 )
{
case 0 : // 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 ;
case 1 : // 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 ( ) ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp ;
effect = 2 ;
}
else
{
u8 toSub ;
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . ability = = 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
{
if ( gCurrentMove ! = MOVE_SNORE & & gCurrentMove ! = MOVE_SLEEP_TALK )
{
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 ( ) ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp ;
effect = 2 ;
}
}
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 2 : // check being frozen
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_FREEZE )
2017-09-17 14:10:32 +02:00
{
if ( Random ( ) % 5 )
{
if ( gBattleMoves [ gCurrentMove ] . effect ! = EFFECT_THAW_HIT ) // unfreezing via a move effect happens in case 13
{
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen ;
gHitMarker | = HITMARKER_NO_ATTACKSTRING ;
}
else
{
gBattleStruct - > atkCancellerTracker + + ;
break ;
}
}
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 ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
}
effect = 2 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 3 : // truant
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . ability = = 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 ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
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 ;
case 4 : // 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 ) ;
gDisableStructs [ gBattlerAttacker ] . rechargeCounter = 0 ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 5 : // flinch
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_FLINCHED )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 & = ~ ( STATUS2_FLINCHED ) ;
gProtectStructs [ gBattlerAttacker ] . flinchImmobility = 1 ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 6 : // 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
{
2018-02-06 23:09:39 +01:00
gProtectStructs [ gBattlerAttacker ] . usedDisabledMove = 1 ;
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 ;
case 7 : // taunt
2018-02-06 23:09:39 +01:00
if ( gDisableStructs [ gBattlerAttacker ] . tauntTimer1 & & gBattleMoves [ gCurrentMove ] . power = = 0 )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gProtectStructs [ gBattlerAttacker ] . usedTauntedMove = 1 ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 8 : // imprisoned
2018-02-06 23:09:39 +01:00
if ( GetImprisonedMovesCount ( gBattlerAttacker , gCurrentMove ) )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gProtectStructs [ gBattlerAttacker ] . usedImprisionedMove = 1 ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 9 : // confusion
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_CONFUSION )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 - - ;
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_CONFUSION )
2017-09-17 14:10:32 +02:00
{
if ( Random ( ) & 1 )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
}
else // confusion dmg
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2018-02-06 23:09:39 +01:00
gBattlerTarget = gBattlerAttacker ;
2018-07-14 22:56:03 +02:00
gBattleMoveDamage = CalculateMoveDamage ( MOVE_NONE , gBattlerAttacker , gBattlerAttacker , TYPE_MYSTERY , 40 , FALSE , FALSE ) ;
2018-02-06 23:09:39 +01:00
gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg = 1 ;
2017-09-17 14:10:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
}
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 ;
case 10 : // 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
{
2018-02-06 23:09:39 +01:00
gProtectStructs [ gBattlerAttacker ] . prlzImmobility = 1 ;
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 ;
case 11 : // 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
{
2017-09-22 21:33:49 +02:00
BattleScriptPush ( BattleScript_MoveUsedIsParalyzedCantAttack ) ;
2017-09-17 14:10:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
2018-02-06 23:09:39 +01:00
gProtectStructs [ gBattlerAttacker ] . loveImmobility = 1 ;
CancelMultiTurnMoves ( gBattlerAttacker ) ;
2017-09-17 14:10:32 +02:00
}
gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 12 : // bide
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_BIDE )
2017-09-17 14:10:32 +02:00
{
2018-02-06 23:09:39 +01:00
gBattleMons [ gBattlerAttacker ] . status2 - = 0x100 ;
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 ;
case 13 : // move thawing
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_FREEZE )
2017-09-17 14:10:32 +02:00
{
if ( gBattleMoves [ gCurrentMove ] . effect = = EFFECT_THAW_HIT )
{
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 ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
}
effect = 2 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2017-11-26 13:26:58 +01:00
case ATKCANCELLER_MAX_CASE :
2017-09-17 14:10:32 +02:00
break ;
}
} while ( gBattleStruct - > atkCancellerTracker ! = ATKCANCELLER_MAX_CASE & & effect = = 0 ) ;
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-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
2017-09-17 15:19:15 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
{
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 )
{
if ( gBattleTypeFlags & BATTLE_TYPE_x800000 )
{
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
{
2018-07-01 11:15:42 +02:00
// FIXME: Compiler insists on moving r4 into r1 before doing the eor.
2017-09-17 15:19:15 +02:00
# ifndef NONMATCHING
2018-07-01 11:15:42 +02:00
register u32 var asm ( " r1 " ) ;
2017-09-17 15:19:15 +02:00
# else
2018-07-01 11:15:42 +02:00
u32 var ;
2017-09-17 15:19:15 +02:00
# endif // NONMATCHING
party = gEnemyParty ;
2018-07-01 11:15:42 +02:00
var = battler ^ BIT_SIDE ;
if ( var = = 0 )
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
}
}
enum
{
CASTFORM_NO_CHANGE , //0
CASTFORM_TO_NORMAL , //1
CASTFORM_TO_FIRE , //2
CASTFORM_TO_WATER , //3
CASTFORM_TO_ICE , //4
} ;
2018-02-06 02:46:59 +01:00
u8 CastformDataTypeChange ( u8 battler )
2017-09-17 15:19:15 +02:00
{
u8 formChange = 0 ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ battler ] . species ! = SPECIES_CASTFORM | | gBattleMons [ battler ] . ability ! = ABILITY_FORECAST | | gBattleMons [ battler ] . hp = = 0 )
2017-09-17 15:19:15 +02:00
return CASTFORM_NO_CHANGE ;
2018-03-01 00:59:52 +01:00
if ( ! WEATHER_HAS_EFFECT & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_NORMAL ) )
2017-09-17 15:19:15 +02:00
{
2018-03-01 00:59:52 +01:00
SET_BATTLER_TYPE ( battler , TYPE_NORMAL ) ;
2017-09-17 15:19:15 +02:00
return CASTFORM_TO_NORMAL ;
}
if ( ! WEATHER_HAS_EFFECT )
return CASTFORM_NO_CHANGE ;
2018-03-01 00:59:52 +01:00
if ( ! ( gBattleWeather & ( WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL_ANY ) ) & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_NORMAL ) )
2017-09-17 15:19:15 +02:00
{
2018-03-01 00:59:52 +01:00
SET_BATTLER_TYPE ( battler , TYPE_NORMAL ) ;
2017-09-17 15:19:15 +02:00
formChange = CASTFORM_TO_NORMAL ;
}
2018-03-01 00:59:52 +01:00
if ( gBattleWeather & WEATHER_SUN_ANY & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_FIRE ) )
2017-09-17 15:19:15 +02:00
{
2018-03-01 00:59:52 +01:00
SET_BATTLER_TYPE ( battler , TYPE_FIRE ) ;
2017-09-17 15:19:15 +02:00
formChange = CASTFORM_TO_FIRE ;
}
2018-03-01 00:59:52 +01:00
if ( gBattleWeather & WEATHER_RAIN_ANY & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_WATER ) )
2017-09-17 15:19:15 +02:00
{
2018-03-01 00:59:52 +01:00
SET_BATTLER_TYPE ( battler , TYPE_WATER ) ;
2017-09-17 15:19:15 +02:00
formChange = CASTFORM_TO_WATER ;
}
2018-03-01 00:59:52 +01:00
if ( gBattleWeather & WEATHER_HAIL_ANY & & ! IS_BATTLER_OF_TYPE ( battler , TYPE_ICE ) )
2017-09-17 15:19:15 +02:00
{
2018-03-01 00:59:52 +01:00
SET_BATTLER_TYPE ( battler , TYPE_ICE ) ;
2017-09-17 15:19:15 +02:00
formChange = CASTFORM_TO_ICE ;
}
return formChange ;
}
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 } ,
[ ENUM_WEATHER_SUN ] = { WEATHER_SUN_TEMPORARY , WEATHER_SUN_PERMANENT , HOLD_EFFECT_HEAT_ROCK } ,
[ 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 } ,
} ;
bool32 TryChangeBattleWeather ( u8 battler , u32 weatherEnumId , bool32 viaAbility )
{
if ( viaAbility & & B_ABILITY_WEATHER < = GEN_5
& & ! ( gBattleWeather & sWeatherFlagsInfo [ weatherEnumId ] [ 1 ] ) )
{
gBattleWeather = ( sWeatherFlagsInfo [ weatherEnumId ] [ 0 ] | sWeatherFlagsInfo [ weatherEnumId ] [ 1 ] ) ;
return TRUE ;
}
else if ( B_ABILITY_WEATHER > GEN_5
& & ! ( gBattleWeather & ( sWeatherFlagsInfo [ weatherEnumId ] [ 0 ] | sWeatherFlagsInfo [ weatherEnumId ] [ 1 ] ) ) )
{
gBattleWeather = ( sWeatherFlagsInfo [ weatherEnumId ] [ 0 ] ) ;
if ( GetBattlerHoldEffect ( battler , TRUE ) = = sWeatherFlagsInfo [ weatherEnumId ] [ 2 ] )
gWishFutureKnock . weatherDuration = 8 ;
else
gWishFutureKnock . weatherDuration = 5 ;
return TRUE ;
}
else
{
return FALSE ;
}
}
2018-02-06 02:46:59 +01:00
u8 AbilityBattleEffects ( u8 caseID , u8 battler , u8 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 ;
u32 moveType ;
u32 i ;
u32 move ;
u8 side ;
u8 target1 ;
if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
return ;
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-07-22 18:40:18 +02:00
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
switch ( gLastUsedAbility )
2017-09-17 15:19:15 +02:00
{
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-07-22 18:40:18 +02:00
switch ( weather_get_current ( ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
case 3 :
case 5 :
case 13 :
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 ;
gBattleScripting . battler = battler ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case 8 :
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 ;
gBattleScripting . battler = battler ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case 12 :
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 ;
2018-02-06 02:46:59 +01:00
gBattleScripting . battler = battler ;
2017-09-17 15:19:15 +02:00
effect + + ;
}
break ;
}
}
2018-07-22 18:40:18 +02:00
if ( effect )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = weather_get_current ( ) ;
BattleScriptPushCursorAndCallback ( BattleScript_OverworldWeatherStarts ) ;
}
2017-09-17 15:19:15 +02:00
break ;
2018-07-22 22:21:47 +02:00
case ABILITY_MOLD_BREAKER :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_TERAVOLT :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_TURBOBLAZE :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 2 ;
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_SLOW_START :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 3 ;
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
BattleScriptPushCursorAndCallback ( BattleScript_SwitchInAbilityMsg ) ;
effect + + ;
}
break ;
case ABILITY_UNNERVE :
if ( ! gSpecialStatuses [ battler ] . switchInAbilityDone )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 4 ;
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
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
{
2018-07-22 18:40:18 +02:00
u8 statId ;
u32 opposingBattler = BATTLE_OPPOSITE ( battler ) ;
u32 opposingDef = gBattleMons [ opposingBattler ] . defense
* gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_DEF ] ] [ 0 ]
/ gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_DEF ] ] [ 1 ] ;
u32 opposingSpDef = gBattleMons [ opposingBattler ] . spDefense
* gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_SPDEF ] ] [ 0 ]
/ gStatStageRatios [ gBattleMons [ opposingBattler ] . statStages [ STAT_SPDEF ] ] [ 1 ] ;
opposingBattler = BATTLE_PARTNER ( opposingBattler ) ;
if ( IsBattlerAlive ( opposingBattler ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02: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
}
2018-07-22 18:40:18 +02:00
if ( opposingSpDef > opposingDef )
statId = STAT_SPATK ;
else
statId = STAT_ATK ;
2018-07-22 22:21:47 +02:00
gSpecialStatuses [ battler ] . switchInAbilityDone = 1 ;
2018-07-22 18:40:18 +02:00
if ( gBattleMons [ battler ] . statStages [ statId ] ! = 0xC )
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 ) ;
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , statId ) ;
BattleScriptPushCursorAndCallback ( BattleScript_AttackerAbilityStatRaiseEnd3 ) ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
}
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 ) ;
gBattleScripting . battler = battler ;
effect + + ;
}
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
{
2018-07-27 23:40:10 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_DrizzleActivates ) ;
2018-07-22 18:40:18 +02:00
gBattleScripting . battler = battler ;
effect + + ;
}
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 ) ;
gBattleScripting . battler = battler ;
effect + + ;
}
break ;
2018-07-27 23:40:10 +02:00
case ABILITY_SNOW_WARNING :
if ( TryChangeBattleWeather ( battler , ENUM_WEATHER_HAIL , TRUE ) )
{
BattleScriptPushCursorAndCallback ( BattleScript_SnowWarningActivates ) ;
gBattleScripting . battler = battler ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_INTIMIDATE :
if ( ! ( gSpecialStatuses [ battler ] . intimidatedMon ) )
{
gStatuses3 [ battler ] | = STATUS3_INTIMIDATE_POKES ;
gSpecialStatuses [ battler ] . intimidatedMon = 1 ;
}
break ;
case ABILITY_FORECAST :
effect = CastformDataTypeChange ( battler ) ;
if ( effect ! = 0 )
{
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
gBattleScripting . battler = battler ;
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
}
break ;
case ABILITY_TRACE :
if ( ! ( gSpecialStatuses [ battler ] . traced ) )
{
gStatuses3 [ battler ] | = STATUS3_TRACE ;
gSpecialStatuses [ battler ] . traced = 1 ;
}
break ;
case ABILITY_CLOUD_NINE :
case ABILITY_AIR_LOCK :
2018-07-22 22:21:47 +02:00
// that's a weird choice for a variable, why not use i or battler?
for ( target1 = 0 ; target1 < gBattlersCount ; target1 + + )
2018-07-22 18:40:18 +02:00
{
2018-07-22 22:21:47 +02:00
effect = CastformDataTypeChange ( target1 ) ;
if ( effect ! = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 22:21:47 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
gBattleScripting . battler = target1 ;
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
break ;
2017-09-17 15:19:15 +02:00
}
}
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 :
if ( ( ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SUN_ANY ) | | Random ( ) % 2 = = 0 )
& & gBattleMons [ battler ] . item = = ITEM_NONE
& & gBattleStruct - > changedItems [ battler ] = = ITEM_NONE
& & ItemId_GetPocket ( gBattleStruct - > usedHeldItems [ battler ] ) = = POCKET_BERRIES )
{
gLastUsedItem = gBattleStruct - > changedItems [ battler ] = gBattleStruct - > usedHeldItems [ battler ] ;
gBattleStruct - > usedHeldItems [ battler ] = ITEM_NONE ;
BattleScriptPushCursorAndCallback ( BattleScript_HarvestActivates ) ;
effect + + ;
}
break ;
2018-07-22 18:40:18 +02:00
case ABILITY_RAIN_DISH :
2018-07-22 19:34:13 +02:00
if ( WEATHER_HAS_EFFECT
& & ( gBattleWeather & WEATHER_RAIN_ANY )
2018-07-22 18:40:18 +02:00
& & gBattleMons [ battler ] . maxHP > gBattleMons [ battler ] . hp )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_RainDishActivates ) ;
gBattleMoveDamage = gBattleMons [ battler ] . maxHP / 16 ;
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 :
if ( WEATHER_HAS_EFFECT
& & ( gBattleWeather & WEATHER_RAIN_ANY )
& & gBattleMons [ battler ] . status1 & STATUS1_ANY )
{
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 :
if ( gBattleMons [ battler ] . statStages [ STAT_SPEED ] < 0xC & & gDisableStructs [ battler ] . isFirstTurn ! = 2 )
{
gBattleMons [ battler ] . statStages [ STAT_SPEED ] + + ;
gBattleScripting . animArg1 = 0x11 ;
gBattleScripting . animArg2 = 0 ;
BattleScriptPushCursorAndCallback ( BattleScript_SpeedBoostActivates ) ;
gBattleScripting . battler = battler ;
2017-09-17 15:19:15 +02:00
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 :
if ( gBattleMons [ BATTLE_OPPOSITE ( battler ) ] . status1 & STATUS1_SLEEP | | gBattleMons [ BATTLE_OPPOSITE ( battler ) ] . status1 & STATUS1_SLEEP )
{
BattleScriptPushCursorAndCallback ( BattleScript_BadDreamsActivates ) ;
effect + + ;
}
break ;
2018-07-26 21:56:23 +02:00
case ABILITY_SOLAR_POWER :
if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SUN_ANY )
{
BattleScriptPushCursorAndCallback ( BattleScript_SolarPowerActivates ) ;
gBattleMoveDamage = gBattleMons [ battler ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
effect + + ;
}
break ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_MOVES_BLOCK : // 2
if ( gLastUsedAbility = = ABILITY_SOUNDPROOF )
{
for ( i = 0 ; sSoundMovesTable [ i ] ! = 0xFFFF ; i + + )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
if ( sSoundMovesTable [ i ] = = move )
break ;
}
if ( sSoundMovesTable [ i ] ! = 0xFFFF )
{
if ( gBattleMons [ gBattlerAttacker ] . status2 & STATUS2_MULTIPLETURNS )
gHitMarker | = HITMARKER_NO_PPDEDUCT ;
gBattlescriptCurrInstr = BattleScript_SoundproofProtected ;
effect = 1 ;
}
}
break ;
case ABILITYEFFECT_ABSORBING : // 3
if ( move )
{
u8 statId ;
switch ( gLastUsedAbility )
{
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 :
if ( moveArg = = TYPE_GRASS )
effect = 2 , statId = STAT_ATK ;
break ;
case ABILITY_FLASH_FIRE :
if ( moveType = = TYPE_FIRE & & ! ( gBattleMons [ battler ] . status1 & STATUS1_FREEZE ) )
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-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
if ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_FlashFireBoost ;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss ;
gBattleResources - > flags - > flags [ battler ] | = RESOURCE_FLAG_FLASH_FIRE ;
effect = 2 ;
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
{
2018-07-22 18:40:18 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
if ( gProtectStructs [ gBattlerAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_FlashFireBoost ;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss ;
2017-11-26 17:15:28 +01:00
effect = 2 ;
}
}
2018-07-22 18:40:18 +02:00
break ;
}
if ( effect = = 1 ) // Drain Hp ability.
{
if ( gBattleMons [ battler ] . maxHP = = gBattleMons [ battler ] . hp )
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
{
2018-07-22 18:40:18 +02:00
if ( gBattleMons [ battler ] . statStages [ statId ] = = 0xC )
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 ;
case ABILITYEFFECT_CONTACT : // 4
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
& & gBattleMons [ battler ] . statStages [ STAT_ATK ] ! = 0xC )
{
gBattleMons [ battler ] . statStages [ STAT_ATK ] + + ;
SET_STATCHANGER ( STAT_ATK , 1 , FALSE ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaise ;
effect + + ;
}
break ;
case ABILITY_RATTLED :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
& & ( moveType = = TYPE_DARK | | moveType = = TYPE_BUG | | moveType = = TYPE_GHOST )
& & gBattleMons [ battler ] . statStages [ STAT_SPEED ] ! = 0xC )
{
gBattleMons [ battler ] . statStages [ STAT_SPEED ] + + ;
SET_STATCHANGER ( STAT_SPEED , 1 , FALSE ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_TargetAbilityStatRaise ;
effect + + ;
}
break ;
case ABILITY_WEAK_ARMOR :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & IsBattlerAlive ( battler )
& & ( gBattleMons [ battler ] . statStages [ STAT_SPEED ] ! = 0xC | | gBattleMons [ battler ] . statStages [ STAT_DEF ] ! = 0 ) )
{
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_WeakArmorActivates ;
effect + + ;
}
break ;
case ABILITY_CURSED_BODY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & TARGET_TURN_DAMAGED
& & gDisableStructs [ gBattlerAttacker ] . disabledMove = = MOVE_NONE
& & IsBattlerAlive ( gBattlerAttacker )
& & ( ( i = GetBattleMonMoveSlot ( & gBattleMons [ gBattlerAttacker ] , gChosenMove ) ) ! = 4 )
& & ( Random ( ) % 3 ) = = 0 )
{
gDisableStructs [ gBattlerAttacker ] . disabledMove = gChosenMove ;
gDisableStructs [ gBattlerAttacker ] . disableTimer1 = 4 ;
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , gChosenMove ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_CursedBodyActivates ;
effect + + ;
}
break ;
case ABILITY_MUMMY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & IsBattlerAlive ( gBattlerAttacker )
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT ) )
{
switch ( gBattleMons [ gBattlerAttacker ] . ability )
{
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 ;
}
}
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 )
& & gBattleMons [ battler ] . statStages [ STAT_ATK ] ! = 0xC )
{
gBattleMons [ battler ] . statStages [ STAT_ATK ] = 0xC ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AngryPointActivates ;
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 + + ;
}
break ;
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
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT ) )
{
2018-07-26 21:56:23 +02:00
gBattleMoveDamage = gBattleMons [ gBattlerAttacker ] . maxHP / 8 ;
2018-07-22 18:40:18 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_RoughSkinActivates ;
effect + + ;
}
break ;
case ABILITY_EFFECT_SPORE :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & TARGET_TURN_DAMAGED
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( Random ( ) % 10 ) = = 0 )
{
do
{
gBattleCommunication [ MOVE_EFFECT_BYTE ] = Random ( ) & 3 ;
} while ( gBattleCommunication [ MOVE_EFFECT_BYTE ] = = 0 ) ;
2017-10-12 17:49:24 +02:00
2018-07-22 18:40:18 +02:00
if ( gBattleCommunication [ MOVE_EFFECT_BYTE ] = = MOVE_EFFECT_BURN )
gBattleCommunication [ MOVE_EFFECT_BYTE ] + = 2 ; // 5 MOVE_EFFECT_PARALYSIS
gBattleCommunication [ MOVE_EFFECT_BYTE ] + = MOVE_EFFECT_AFFECTS_USER ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2018-07-22 18:40:18 +02:00
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
2017-09-17 15:19:15 +02:00
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
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
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( Random ( ) % 3 ) = = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_POISON ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2018-07-22 18:40:18 +02:00
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
2017-09-17 15:19:15 +02:00
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
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
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( Random ( ) % 3 ) = = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_PARALYSIS ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_FLAME_BODY :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & TARGET_TURN_DAMAGED
& & ( Random ( ) % 3 ) = = 0 )
{
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_CUTE_CHARM :
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBattlerAttacker ] . confusionSelfDmg
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & TARGET_TURN_DAMAGED
& & gBattleMons [ gBattlerTarget ] . hp ! = 0
& & ( Random ( ) % 3 ) = = 0
& & gBattleMons [ gBattlerAttacker ] . ability ! = ABILITY_OBLIVIOUS
& & 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 ;
}
break ;
case ABILITYEFFECT_IMMUNITY : // 5
for ( battler = 0 ; battler < gBattlersCount ; battler + + )
{
switch ( gBattleMons [ battler ] . ability )
{
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 :
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 )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
effect = 3 ;
}
break ;
}
if ( effect )
{
switch ( effect )
{
case 1 : // status cleared
gBattleMons [ battler ] . status1 = 0 ;
break ;
case 2 : // get rid of confusion
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
break ;
case 3 : // get rid of infatuation
gBattleMons [ battler ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
2017-09-17 15:19:15 +02:00
break ;
}
2018-07-22 18:40:18 +02:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus ;
gBattleScripting . battler = battler ;
gActiveBattler = battler ;
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 + + )
{
if ( gBattleMons [ battler ] . ability = = ABILITY_FORECAST )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
effect = CastformDataTypeChange ( battler ) ;
if ( effect )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
gBattleScripting . battler = battler ;
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
return effect ;
}
}
}
break ;
case ABILITYEFFECT_SYNCHRONIZE : // 7
if ( gLastUsedAbility = = ABILITY_SYNCHRONIZE & & ( gHitMarker & HITMARKER_SYNCHRONISE_EFFECT ) )
{
gHitMarker & = ~ ( HITMARKER_SYNCHRONISE_EFFECT ) ;
gBattleStruct - > synchronizeMoveEffect & = ~ ( MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN ) ;
if ( gBattleStruct - > synchronizeMoveEffect = = MOVE_EFFECT_TOXIC )
gBattleStruct - > synchronizeMoveEffect = MOVE_EFFECT_POISON ;
gBattleCommunication [ MOVE_EFFECT_BYTE ] = gBattleStruct - > synchronizeMoveEffect + MOVE_EFFECT_AFFECTS_USER ;
gBattleScripting . battler = gBattlerTarget ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_SynchronizeActivates ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITYEFFECT_ATK_SYNCHRONIZE : // 8
if ( gLastUsedAbility = = ABILITY_SYNCHRONIZE & & ( gHitMarker & HITMARKER_SYNCHRONISE_EFFECT ) )
{
gHitMarker & = ~ ( HITMARKER_SYNCHRONISE_EFFECT ) ;
gBattleStruct - > synchronizeMoveEffect & = ~ ( MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN ) ;
if ( gBattleStruct - > synchronizeMoveEffect = = MOVE_EFFECT_TOXIC )
gBattleStruct - > synchronizeMoveEffect = MOVE_EFFECT_POISON ;
gBattleCommunication [ MOVE_EFFECT_BYTE ] = gBattleStruct - > synchronizeMoveEffect ;
gBattleScripting . battler = gBattlerAttacker ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_SynchronizeActivates ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITYEFFECT_INTIMIDATE1 : // 9
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_INTIMIDATE & & gStatuses3 [ i ] & STATUS3_INTIMIDATE_POKES )
{
gLastUsedAbility = ABILITY_INTIMIDATE ;
gStatuses3 [ i ] & = ~ ( STATUS3_INTIMIDATE_POKES ) ;
BattleScriptPushCursorAndCallback ( BattleScript_82DB4B8 ) ;
gBattleStruct - > intimidateBattler = i ;
effect + + ;
break ;
}
}
break ;
case ABILITYEFFECT_TRACE : // 11
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_TRACE & & ( gStatuses3 [ i ] & STATUS3_TRACE ) )
{
u8 target2 ;
side = ( GetBattlerPosition ( i ) ^ BIT_SIDE ) & BIT_SIDE ; // side of the opposing pokemon
target1 = GetBattlerAtPosition ( side ) ;
target2 = GetBattlerAtPosition ( side + BIT_FLANK ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
if ( gBattleMons [ target1 ] . ability ! = 0 & & gBattleMons [ target1 ] . hp ! = 0
& & gBattleMons [ target2 ] . ability ! = 0 & & gBattleMons [ target2 ] . hp ! = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gActiveBattler = GetBattlerAtPosition ( ( ( Random ( ) & 1 ) * 2 ) | side ) ;
gBattleMons [ i ] . ability = gBattleMons [ gActiveBattler ] . ability ;
gLastUsedAbility = gBattleMons [ gActiveBattler ] . ability ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
else if ( gBattleMons [ target1 ] . ability ! = 0 & & gBattleMons [ target1 ] . hp ! = 0 )
2017-09-17 15:19:15 +02:00
{
2018-02-06 02:46:59 +01:00
gActiveBattler = target1 ;
2018-07-22 18:40:18 +02:00
gBattleMons [ i ] . ability = gBattleMons [ gActiveBattler ] . ability ;
gLastUsedAbility = gBattleMons [ gActiveBattler ] . ability ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
else if ( gBattleMons [ target2 ] . ability ! = 0 & & gBattleMons [ target2 ] . hp ! = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gActiveBattler = target2 ;
gBattleMons [ i ] . ability = gBattleMons [ gActiveBattler ] . ability ;
gLastUsedAbility = gBattleMons [ gActiveBattler ] . ability ;
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
{
2018-07-22 18:40:18 +02:00
gActiveBattler = target1 ;
if ( gBattleMons [ target1 ] . ability & & gBattleMons [ target1 ] . hp )
{
gBattleMons [ i ] . ability = gBattleMons [ target1 ] . ability ;
gLastUsedAbility = gBattleMons [ target1 ] . ability ;
effect + + ;
}
}
if ( effect )
{
BattleScriptPushCursorAndCallback ( BattleScript_TraceActivates ) ;
gStatuses3 [ i ] & = ~ ( STATUS3_TRACE ) ;
gBattleScripting . battler = i ;
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 ;
case ABILITYEFFECT_INTIMIDATE2 : // 10
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_INTIMIDATE & & ( gStatuses3 [ i ] & STATUS3_INTIMIDATE_POKES ) )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ABILITY_INTIMIDATE ;
gStatuses3 [ i ] & = ~ ( STATUS3_INTIMIDATE_POKES ) ;
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_82DB4C1 ;
gBattleStruct - > intimidateBattler = i ;
effect + + ;
break ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_CHECK_OTHER_SIDE : // 12
side = GetBattlerSide ( battler ) ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( GetBattlerSide ( i ) ! = side & & gBattleMons [ i ] . ability = = ability )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ability ;
effect = i + 1 ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_CHECK_BATTLER_SIDE : // 13
side = GetBattlerSide ( battler ) ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( GetBattlerSide ( i ) = = side & & gBattleMons [ i ] . ability = = ability )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ability ;
effect = i + 1 ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_CHECK_ON_FIELD : // 19
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability & & gBattleMons [ i ] . hp ! = 0 )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ability ;
effect = i + 1 ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER : // 15
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability & & i ! = battler )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ability ;
effect = i + 1 ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_COUNT_OTHER_SIDE : // 16
side = GetBattlerSide ( battler ) ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( GetBattlerSide ( i ) ! = side & & gBattleMons [ i ] . ability = = ability )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ability ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
}
break ;
case ABILITYEFFECT_COUNT_BATTLER_SIDE : // 17
side = GetBattlerSide ( battler ) ;
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( GetBattlerSide ( i ) = = side & & gBattleMons [ i ] . ability = = ability )
2017-09-17 15:19:15 +02:00
{
2018-07-22 18:40:18 +02:00
gLastUsedAbility = ability ;
effect + + ;
2017-09-17 15:19:15 +02:00
}
}
2018-07-22 18:40:18 +02:00
break ;
case ABILITYEFFECT_COUNT_ON_FIELD : // 18
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability & & i ! = battler )
{
gLastUsedAbility = ability ;
effect + + ;
}
}
break ;
2017-09-17 15:19:15 +02:00
}
2018-07-22 18:40:18 +02:00
if ( effect & & caseID < ABILITYEFFECT_CHECK_OTHER_SIDE & & gLastUsedAbility ! = 0xFF )
RecordAbilityBattle ( battler , gLastUsedAbility ) ;
2017-09-17 15:19:15 +02:00
return effect ;
}
2017-09-17 17:14:32 +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
} ;
2018-07-28 16:33:01 +02:00
// second argument is 1/X of current hp compared to max hp
static bool32 HasEnoughHpToEatBerry ( u8 battlerId , u32 hpFraction )
2017-09-17 17:14:32 +02:00
{
2018-07-28 16:33:01 +02:00
if ( gBattleMons [ battlerId ] . hp < = gBattleMons [ battlerId ] . maxHP / hpFraction )
2017-09-17 17:14:32 +02:00
{
2018-07-28 16:33:01 +02:00
return TRUE ;
2017-09-17 17:14:32 +02:00
}
2018-07-28 16:33:01 +02:00
else if ( hpFraction < = 4 & & GetBattlerAbility ( battlerId ) = = ABILITY_GLUTTONY
& & 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
}
else
{
2018-07-28 16:33:01 +02:00
return FALSE ;
2017-09-17 17:14:32 +02:00
}
2018-07-28 16:33:01 +02:00
}
2017-09-17 17:14:32 +02:00
2018-07-28 16:33:01 +02:00
u8 ItemBattleEffects ( u8 caseID , u8 battlerId , bool8 moveTurn )
{
int i = 0 ;
u8 effect = ITEM_NO_EFFECT ;
u8 changedPP = 0 ;
u8 battlerHoldEffect , atkHoldEffect ;
u8 battlerHoldEffectParam , atkHoldEffectParam ;
u16 atkItem ;
gLastUsedItem = gBattleMons [ battlerId ] . item ;
battlerHoldEffect = GetBattlerHoldEffect ( battlerId , TRUE ) ;
battlerHoldEffectParam = GetBattlerHoldEffectParam ( battlerId ) ;
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 :
2018-07-16 20:47:30 +02:00
switch ( battlerHoldEffect )
2017-09-17 17:14:32 +02:00
{
case HOLD_EFFECT_DOUBLE_PRIZE :
2018-02-08 11:17:41 +01:00
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
2017-09-17 17:14:32 +02:00
gBattleStruct - > moneyMultiplier = 2 ;
break ;
case HOLD_EFFECT_RESTORE_STATS :
2017-11-26 11:55:17 +01:00
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . statStages [ i ] < 6 )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . statStages [ i ] = 6 ;
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 ;
}
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 :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & HasEnoughHpToEatBerry ( battlerId , 2 ) )
2017-09-17 17:14:32 +02:00
{
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = battlerHoldEffectParam ;
if ( gBattleMons [ battlerId ] . hp + battlerHoldEffectParam > gBattleMons [ battlerId ] . maxHP )
2018-02-08 11:17:41 +01:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
gBattleMoveDamage * = - 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = 4 ;
}
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 ;
2018-02-08 11:17:41 +01:00
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
mon = & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] ;
2017-09-17 17:14:32 +02:00
else
2018-02-08 11:17:41 +01:00
mon = & gEnemyParty [ gBattlerPartyIndexes [ battlerId ] ] ;
2017-09-17 17:14:32 +02:00
for ( i = 0 ; i < 4 ; i + + )
{
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 ;
}
if ( i ! = 4 )
{
u8 maxPP = CalculatePPWithBonus ( move , ppBonuses , i ) ;
2018-07-16 20:47:30 +02:00
if ( changedPP + battlerHoldEffectParam > maxPP )
2017-09-17 17:14:32 +02:00
changedPP = maxPP ;
else
2018-07-16 20:47:30 +02:00
changedPP = changedPP + battlerHoldEffectParam ;
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 :
2017-11-26 11:55:17 +01:00
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . statStages [ i ] < 6 )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . statStages [ i ] = 6 ;
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_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 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp + gBattleMoveDamage > gBattleMons [ battlerId ] . maxHP )
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
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 ;
// nice copy/paste there gamefreak, making a function for confuse berries was too much eh?
case HOLD_EFFECT_CONFUSE_SPICY :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & HasEnoughHpToEatBerry ( battlerId , 2 ) )
2017-09-17 17:14:32 +02:00
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_SPICY ) ;
2017-11-26 11:55:17 +01:00
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / battlerHoldEffectParam ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp + gBattleMoveDamage > gBattleMons [ battlerId ] . maxHP )
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
gBattleMoveDamage * = - 1 ;
2018-02-08 11:17:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , FLAVOR_SPICY ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_DRY :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & HasEnoughHpToEatBerry ( battlerId , 2 ) )
2017-09-17 17:14:32 +02:00
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_DRY ) ;
2017-11-26 11:55:17 +01:00
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / battlerHoldEffectParam ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp + gBattleMoveDamage > gBattleMons [ battlerId ] . maxHP )
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
gBattleMoveDamage * = - 1 ;
2018-02-08 11:17:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , FLAVOR_DRY ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_SWEET :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & HasEnoughHpToEatBerry ( battlerId , 2 ) )
2017-09-17 17:14:32 +02:00
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_SWEET ) ;
2017-11-26 11:55:17 +01:00
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / battlerHoldEffectParam ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp + gBattleMoveDamage > gBattleMons [ battlerId ] . maxHP )
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
gBattleMoveDamage * = - 1 ;
2018-02-08 11:17:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , FLAVOR_SWEET ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_BITTER :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & HasEnoughHpToEatBerry ( battlerId , 2 ) )
2017-09-17 17:14:32 +02:00
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_BITTER ) ;
2017-11-26 11:55:17 +01:00
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / battlerHoldEffectParam ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp + gBattleMoveDamage > gBattleMons [ battlerId ] . maxHP )
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
gBattleMoveDamage * = - 1 ;
2018-02-08 11:17:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , FLAVOR_BITTER ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_SOUR :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & HasEnoughHpToEatBerry ( battlerId , 2 ) )
2017-09-17 17:14:32 +02:00
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_SOUR ) ;
2017-11-26 11:55:17 +01:00
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP / battlerHoldEffectParam ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . hp + gBattleMoveDamage > gBattleMons [ battlerId ] . maxHP )
gBattleMoveDamage = gBattleMons [ battlerId ] . maxHP - gBattleMons [ battlerId ] . hp ;
2017-09-17 17:14:32 +02:00
gBattleMoveDamage * = - 1 ;
2018-02-08 11:17:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ battlerId ] . personality , FLAVOR_SOUR ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
// copy/paste again, smh
case HOLD_EFFECT_ATTACK_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & gBattleMons [ battlerId ] . statStages [ STAT_ATK ] < 0xC & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 12:13:29 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_ATK ) ;
2017-11-26 11:55:17 +01:00
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , STRINGID_STATROSE ) ;
2017-09-17 17:14:32 +02:00
2018-02-08 11:17:41 +01:00
gEffectBattler = battlerId ;
2018-02-08 12:13:29 +01:00
SET_STATCHANGER ( STAT_ATK , 1 , FALSE ) ;
gBattleScripting . animArg1 = 0xE + STAT_ATK ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_DEFENSE_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & gBattleMons [ battlerId ] . statStages [ STAT_DEF ] < 0xC & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 12:13:29 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_DEF ) ;
2017-09-17 17:14:32 +02:00
2018-02-08 11:17:41 +01:00
gEffectBattler = battlerId ;
2018-02-08 12:13:29 +01:00
SET_STATCHANGER ( STAT_DEF , 1 , FALSE ) ;
gBattleScripting . animArg1 = 0xE + STAT_DEF ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_SPEED_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & gBattleMons [ battlerId ] . statStages [ STAT_SPEED ] < 0xC & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 12:13:29 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_SPEED ) ;
2017-09-17 17:14:32 +02:00
2018-02-08 11:17:41 +01:00
gEffectBattler = battlerId ;
2018-02-08 12:13:29 +01:00
SET_STATCHANGER ( STAT_SPEED , 1 , FALSE ) ;
gBattleScripting . animArg1 = 0xE + STAT_SPEED ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_SP_ATTACK_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & gBattleMons [ battlerId ] . statStages [ STAT_SPATK ] < 0xC & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 12:13:29 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_SPATK ) ;
2017-09-17 17:14:32 +02:00
2018-02-08 11:17:41 +01:00
gEffectBattler = battlerId ;
2018-02-08 12:13:29 +01:00
SET_STATCHANGER ( STAT_SPATK , 1 , FALSE ) ;
gBattleScripting . animArg1 = 0xE + STAT_SPATK ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_SP_DEFENSE_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & gBattleMons [ battlerId ] . statStages [ STAT_SPDEF ] < 0xC & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
2017-09-17 17:14:32 +02:00
{
2018-02-08 12:13:29 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_SPDEF ) ;
2017-09-17 17:14:32 +02:00
2018-02-08 11:17:41 +01:00
gEffectBattler = battlerId ;
2018-02-08 12:13:29 +01:00
SET_STATCHANGER ( STAT_SPDEF , 1 , FALSE ) ;
gBattleScripting . animArg1 = 0xE + STAT_SPDEF ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_CRITICAL_UP :
2018-07-28 16:33:01 +02:00
if ( ! moveTurn & & ! ( gBattleMons [ battlerId ] . status2 & STATUS2_FOCUS_ENERGY ) & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
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 )
2017-09-17 17:14:32 +02:00
{
for ( i = 0 ; i < 5 ; i + + )
{
2018-02-08 12:13:29 +01:00
if ( gBattleMons [ battlerId ] . statStages [ STAT_ATK + i ] < 0xC )
2017-09-17 17:14:32 +02:00
break ;
}
2018-07-28 16:33:01 +02:00
if ( i ! = 5 & & HasEnoughHpToEatBerry ( battlerId , battlerHoldEffectParam ) )
2017-09-17 17:14:32 +02:00
{
do
{
i = Random ( ) % 5 ;
2018-02-08 12:13:29 +01:00
} while ( gBattleMons [ battlerId ] . statStages [ STAT_ATK + i ] = = 0xC ) ;
2017-09-17 17:14:32 +02:00
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , i + 1 ) ;
gBattleTextBuff2 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff2 [ 1 ] = B_BUFF_STRING ;
gBattleTextBuff2 [ 2 ] = STRINGID_STATSHARPLY ;
gBattleTextBuff2 [ 3 ] = STRINGID_STATSHARPLY > > 8 ;
gBattleTextBuff2 [ 4 ] = B_BUFF_STRING ;
gBattleTextBuff2 [ 5 ] = STRINGID_STATROSE ;
gBattleTextBuff2 [ 6 ] = STRINGID_STATROSE > > 8 ;
2017-09-17 17:14:32 +02:00
gBattleTextBuff2 [ 7 ] = EOS ;
2018-02-08 11:17:41 +01:00
gEffectBattler = battlerId ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( i + 1 , 2 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0x21 + i + 6 ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
}
break ;
case HOLD_EFFECT_CURE_PAR :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE )
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 :
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 ] . 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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_ANY | | gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
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 ) )
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
else
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
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 ;
case HOLD_EFFECT_CURE_ATTRACT :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_INFATUATION )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
2017-09-17 17:14:32 +02:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureChosenStatusEnd2 ) ;
2017-09-17 17:14:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
}
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-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 :
2018-02-08 11:17:41 +01:00
if ( ! ( gBattleMons [ battlerId ] . status2 & STATUS2_TRANSFORMED ) & & ! ( gDisableStructs [ battlerId ] . unk18_b & gBitTable [ i ] ) )
gBattleMons [ battlerId ] . pp [ i ] = changedPP ;
2017-09-17 17:14:32 +02:00
break ;
}
}
}
break ;
case 2 :
break ;
case 3 :
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 ) ;
battlerHoldEffectParam = GetBattlerHoldEffectParam ( battlerId ) ;
2018-07-16 20:47:30 +02:00
switch ( battlerHoldEffect )
2017-09-17 17:14:32 +02:00
{
case HOLD_EFFECT_CURE_PAR :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PSN_ANY )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_BURN )
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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_FREEZE )
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 :
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 ] . 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 :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
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 ;
case HOLD_EFFECT_CURE_ATTRACT :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status2 & STATUS2_INFATUATION )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
2017-09-17 17:14:32 +02:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_CURE_STATUS :
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . status1 & STATUS1_ANY | | gBattleMons [ battlerId ] . status2 & STATUS2_CONFUSION )
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 ( ) ;
2017-09-17 17:14:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_RESTORE_STATS :
2017-11-26 11:55:17 +01:00
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
if ( gBattleMons [ battlerId ] . statStages [ i ] < 6 )
2017-09-17 17:14:32 +02:00
{
2018-02-08 11:17:41 +01:00
gBattleMons [ battlerId ] . statStages [ i ] = 6 ;
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-07-28 16:33:01 +02:00
return effect ;
2017-09-17 17:14:32 +02:00
}
break ;
}
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 = battlerId ;
2018-02-06 20:48:02 +01:00
BtlController_EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBattler ] . status1 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-09-17 17:14:32 +02:00
break ;
}
}
break ;
case 4 :
if ( gBattleMoveDamage )
{
switch ( atkHoldEffect )
{
case HOLD_EFFECT_FLINCH :
2018-01-16 22:12:38 +01:00
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
2018-03-01 00:59:52 +01:00
& & TARGET_TURN_DAMAGED
2018-07-16 20:47:30 +02:00
& & ( Random ( ) % 100 ) < atkHoldEffectParam
2017-09-17 17:14:32 +02:00
& & gBattleMoves [ gCurrentMove ] . flags & FLAG_KINGSROCK_AFFECTED
2018-02-06 23:09:39 +01:00
& & gBattleMons [ gBattlerTarget ] . hp )
2017-09-17 17:14:32 +02:00
{
2017-12-02 14:08:55 +01:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_FLINCH ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
SetMoveEffect ( 0 , 0 ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPop ( ) ;
2017-09-17 17:14:32 +02:00
}
break ;
case HOLD_EFFECT_SHELL_BELL :
2018-01-16 22:12:38 +01:00
if ( ! ( gMoveResultFlags & MOVE_RESULT_NO_EFFECT )
2018-02-07 22:53:40 +01:00
& & gSpecialStatuses [ gBattlerTarget ] . dmg ! = 0
& & gSpecialStatuses [ gBattlerTarget ] . dmg ! = 0xFFFF
2018-02-06 23:09:39 +01:00
& & gBattlerAttacker ! = gBattlerTarget
& & gBattleMons [ gBattlerAttacker ] . hp ! = gBattleMons [ gBattlerAttacker ] . maxHP
& & gBattleMons [ gBattlerAttacker ] . hp ! = 0 )
2017-09-17 17:14:32 +02:00
{
gLastUsedItem = atkItem ;
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = gBattlerAttacker ;
2018-02-06 23:09:39 +01:00
gBattleScripting . battler = gBattlerAttacker ;
2018-07-16 20:47:30 +02:00
gBattleMoveDamage = ( gSpecialStatuses [ gBattlerTarget ] . dmg / atkHoldEffectParam ) * - 1 ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = - 1 ;
2018-02-07 22:53:40 +01:00
gSpecialStatuses [ gBattlerTarget ] . dmg = 0 ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret ;
effect + + ;
}
break ;
}
}
break ;
}
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 ] ( ) ;
}
2018-03-01 00:59:52 +01:00
u8 GetMoveTarget ( u16 move , u8 setTarget )
2017-09-17 17:14:32 +02:00
{
2018-07-01 11:15:42 +02:00
u8 targetBattler = 0 ;
2017-09-17 17:14:32 +02:00
u8 moveTarget ;
u8 side ;
2018-03-01 00:59:52 +01:00
if ( setTarget )
moveTarget = setTarget - 1 ;
2017-09-17 17:14:32 +02:00
else
moveTarget = gBattleMoves [ move ] . target ;
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 ;
2017-09-17 17:14:32 +02:00
if ( gSideTimers [ side ] . followmeTimer & & gBattleMons [ gSideTimers [ side ] . followmeTarget ] . hp )
2018-07-01 11:15:42 +02:00
targetBattler = gSideTimers [ side ] . followmeTarget ;
2017-09-17 17:14:32 +02:00
else
{
2018-02-06 23:09:39 +01:00
side = GetBattlerSide ( gBattlerAttacker ) ;
2017-09-17 17:14:32 +02:00
do
{
2018-07-01 11:15:42 +02:00
targetBattler = Random ( ) % gBattlersCount ;
} while ( targetBattler = = gBattlerAttacker | | side = = GetBattlerSide ( targetBattler ) | | gAbsentBattlerFlags & gBitTable [ targetBattler ] ) ;
2017-09-17 17:14:32 +02:00
if ( gBattleMoves [ move ] . type = = TYPE_ELECTRIC
2018-02-06 23:09:39 +01:00
& & AbilityBattleEffects ( ABILITYEFFECT_COUNT_OTHER_SIDE , gBattlerAttacker , ABILITY_LIGHTNING_ROD , 0 , 0 )
2018-07-01 11:15:42 +02:00
& & gBattleMons [ targetBattler ] . ability ! = 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 ) ;
gSpecialStatuses [ targetBattler ] . lightningRodRedirected = 1 ;
2017-09-17 17:14:32 +02:00
}
2018-07-22 19:34:13 +02:00
else if ( gBattleMoves [ move ] . type = = TYPE_WATER
& & AbilityBattleEffects ( ABILITYEFFECT_COUNT_OTHER_SIDE , gBattlerAttacker , ABILITY_STORM_DRAIN , 0 , 0 )
& & gBattleMons [ targetBattler ] . ability ! = ABILITY_STORM_DRAIN )
{
targetBattler ^ = BIT_FLANK ;
RecordAbilityBattle ( targetBattler , gBattleMons [ targetBattler ] . ability ) ;
gSpecialStatuses [ targetBattler ] . stormDrainRedirected = 1 ;
}
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 ) ;
if ( gAbsentBattlerFlags & gBitTable [ targetBattler ] )
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 ;
2017-09-17 17:14:32 +02:00
if ( gSideTimers [ side ] . followmeTimer & & gBattleMons [ gSideTimers [ side ] . followmeTarget ] . hp )
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 )
2017-09-17 17:14:32 +02:00
{
2018-02-06 23:09:39 +01:00
if ( GetBattlerSide ( gBattlerAttacker ) = = B_SIDE_PLAYER )
2017-09-17 17:14:32 +02:00
{
if ( Random ( ) & 1 )
2018-07-01 11:15:42 +02:00
targetBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
2017-09-17 17:14:32 +02:00
else
2018-07-01 11:15:42 +02:00
targetBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
2017-09-17 17:14:32 +02:00
}
else
{
if ( Random ( ) & 1 )
2018-07-01 11:15:42 +02:00
targetBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-09-17 17:14:32 +02:00
else
2018-07-01 11:15:42 +02:00
targetBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
2017-09-17 17:14:32 +02:00
}
2018-07-01 11:15:42 +02:00
if ( gAbsentBattlerFlags & gBitTable [ targetBattler ] )
targetBattler ^ = BIT_FLANK ;
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-07-01 11:15:42 +02:00
targetBattler = gBattlerAttacker ;
2017-09-17 17:14:32 +02:00
break ;
}
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
}
2018-02-08 11:17:41 +01:00
static bool32 HasObedientBitSet ( 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 ;
2018-02-08 11:17:41 +01:00
return GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ battlerId ] ] , MON_DATA_OBEDIENCE , 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 ;
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000 ) )
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 ;
2018-02-06 23:09:39 +01:00
if ( HasObedientBitSet ( gBattlerAttacker ) ) // only if species is 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
{
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB695 ;
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
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = Random ( ) & 3 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
return 1 ;
}
else // use a random move
{
do
{
2018-02-08 11:17:41 +01:00
gCurrMovePos = gChosenMovePos = Random ( ) & 3 ;
2017-09-17 17:14:32 +02:00
} while ( gBitTable [ gCurrMovePos ] & calc ) ;
2018-02-06 23:09:39 +01:00
gRandomMove = gBattleMons [ gBattlerAttacker ] . moves [ gCurrMovePos ] ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove ;
2018-02-06 23:09:39 +01:00
gBattlerTarget = GetMoveTarget ( gRandomMove , 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 ) ;
2018-02-06 23:09:39 +01:00
if ( calc < obedienceLevel & & ! ( gBattleMons [ gBattlerAttacker ] . status1 & STATUS1_ANY ) & & gBattleMons [ gBattlerAttacker ] . ability ! = ABILITY_VITAL_SPIRIT & & gBattleMons [ gBattlerAttacker ] . ability ! = ABILITY_INSOMNIA )
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 )
{
2018-07-14 22:56:03 +02:00
gBattleMoveDamage = CalculateMoveDamage ( MOVE_NONE , gBattlerAttacker , gBattlerAttacker , TYPE_MYSTERY , 40 , FALSE , FALSE ) ;
2018-02-06 23:09:39 +01:00
gBattlerTarget = gBattlerAttacker ;
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB6F0 ;
2017-09-17 17:14:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
return 2 ;
}
else
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = Random ( ) & 3 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
return 1 ;
}
}
}
2018-07-14 16:41:14 +02:00
u32 GetBattlerAbility ( u8 battlerId )
{
if ( gStatuses3 [ battlerId ] & STATUS3_GASTRO_ACID )
return ABILITY_NONE ;
else if ( ( gBattleMons [ gBattlerAttacker ] . ability = = ABILITY_MOLD_BREAKER
| | gBattleMons [ gBattlerAttacker ] . ability = = ABILITY_TERAVOLT
| | gBattleMons [ gBattlerAttacker ] . ability = = ABILITY_TURBOBLAZE )
& & sAbilitiesAffectedByMoldBreaker [ gBattleMons [ battlerId ] . ability ]
& & gBattlerByTurnOrder [ gCurrentTurnActionNumber ] = = gBattlerAttacker
& & gActionsByTurnOrder [ gBattlerByTurnOrder [ gBattlerAttacker ] ] = = B_ACTION_USE_MOVE
& & gCurrentTurnActionNumber < gBattlersCount
& & ! ( gStatuses3 [ gBattlerAttacker ] & STATUS3_GASTRO_ACID ) )
return ABILITY_NONE ;
else
return gBattleMons [ battlerId ] . ability ;
}
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 ;
if ( gBattleMons [ battlerId ] . ability = = ABILITY_KLUTZ & & ! ( gStatuses3 [ battlerId ] & STATUS3_GASTRO_ACID ) )
return HOLD_EFFECT_NONE ;
}
gPotentialItemEffectBattler = battlerId ;
if ( gBattleMons [ battlerId ] . item = = ITEM_ENIGMA_BERRY )
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 ) )
return FALSE ;
else if ( GetBattlerAbility ( battlerAtk ) = = ABILITY_LONG_REACH )
return FALSE ;
else if ( GetBattlerHoldEffect ( battlerAtk , TRUE ) = = HOLD_EFFECT_PROTECTIVE_PADS )
return FALSE ;
else
return TRUE ;
}
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 ;
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
return TRUE ;
}
bool32 IsBattlerAlive ( u8 battlerId )
{
if ( gBattleMons [ battlerId ] . hp = = 0 )
return FALSE ;
else if ( battlerId > = gBattlersCount )
return FALSE ;
else if ( gAbsentBattlerFlags & gBitTable [ battlerId ] )
return FALSE ;
else
return TRUE ;
}
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 )
{
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 ;
if ( gDisableStructs [ battlerId ] . autonomizeCount )
weight - = 1000 * gDisableStructs [ battlerId ] . autonomizeCount ;
if ( weight = = 0 )
weight = 1 ;
return weight ;
}
u32 CountBattlerStatIncreases ( u8 battlerId , bool32 countEvasionAcc )
{
u32 i ;
u32 count = 0 ;
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
{
if ( ( i = = STAT_ACC | | i = = STAT_EVASION ) & & ! countEvasionAcc )
continue ;
if ( gBattleMons [ battlerId ] . statStages [ i ] > 6 ) // Stat is increased.
count + = gBattleMons [ battlerId ] . statStages [ i ] - 6 ;
}
return count ;
}
u32 GetMoveTargetCount ( u16 move , u8 battlerAtk , u8 battlerDef )
{
switch ( gBattleMoves [ move ] . target )
{
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 ) ;
}
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 :
// todo
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 :
for ( i = 1 ; i < ( 5 - gDisableStructs [ battlerAtk ] . rolloutCounter1 ) ; i + + )
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 :
if ( gCurrentActionFuncId = = B_ACTION_SWITCH )
basePower * = 2 ;
break ;
case EFFECT_NATURAL_GIFT :
// todo
break ;
case EFFECT_WAKE_UP_SLAP :
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP )
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 :
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_ANY )
basePower * = 2 ;
break ;
case EFFECT_ASSURANCE :
if ( gSpecialStatuses [ battlerDef ] . physicalDmg ! = 0 | | gSpecialStatuses [ battlerDef ] . specialDmg ! = 0 )
basePower * = 2 ;
break ;
case EFFECT_TRUMP_CARD :
i = GetBattleMonMoveSlot ( & gBattleMons [ battlerAtk ] , move ) ;
if ( i ! = 4 )
{
switch ( gBattleMons [ battlerAtk ] . pp [ i ] )
{
case 0 :
basePower = 200 ;
break ;
case 1 :
basePower = 80 ;
break ;
case 2 :
basePower = 60 ;
break ;
case 3 :
basePower = 50 ;
break ;
default :
basePower = 40 ;
break ;
}
}
break ;
case EFFECT_ACROBATICS :
if ( gBattleMons [ battlerAtk ] . item = = ITEM_NONE )
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 ) ;
if ( weight > = 5 )
basePower = 120 ;
else if ( weight = = 4 )
basePower = 100 ;
else if ( weight = = 3 )
basePower = 80 ;
else if ( weight = = 2 )
basePower = 60 ;
else
basePower = 40 ;
break ;
case EFFECT_PUNISHMENT :
basePower = 60 + ( CountBattlerStatIncreases ( battlerAtk , FALSE ) * 20 ) ;
if ( basePower > 200 )
basePower = 200 ;
break ;
case EFFECT_STORED_POWER :
basePower = 60 + ( CountBattlerStatIncreases ( battlerAtk , TRUE ) * 20 ) ;
break ;
case EFFECT_ELECTRO_BALL :
speed = GetBattlerTotalSpeedStat ( battlerAtk ) / GetBattlerTotalSpeedStat ( battlerDef ) ;
if ( speed > = ARRAY_COUNT ( sSpeedDiffToDmgTable ) )
speed = ARRAY_COUNT ( sSpeedDiffToDmgTable ) - 1 ;
basePower = sSpeedDiffToDmgTable [ speed ] ;
break ;
case EFFECT_GYRO_BALL :
basePower = ( ( 25 * GetBattlerTotalSpeedStat ( battlerDef ) ) / GetBattlerTotalSpeedStat ( battlerAtk ) ) + 1 ;
if ( basePower > 150 )
basePower = 150 ;
break ;
case EFFECT_ECHOED_VOICE :
if ( gFieldTimers . echoVoiceCounter ! = 0 )
{
if ( gFieldTimers . echoVoiceCounter > = 5 )
basePower * = 5 ;
else
basePower * = gFieldTimers . echoVoiceCounter ;
}
break ;
case EFFECT_PAYBACK :
if ( GetBattlerTurnOrderNum ( battlerAtk ) > GetBattlerTurnOrderNum ( battlerDef ) )
basePower * = 2 ;
break ;
case EFFECT_GUST :
case EFFECT_TWISTER :
if ( gStatuses3 [ battlerDef ] & STATUS3_ON_AIR )
basePower * = 2 ;
break ;
case EFFECT_ROUND :
if ( gChosenMoveByBattler [ BATTLE_PARTNER ( battlerAtk ) ] = = MOVE_ROUND & & ! ( gAbsentBattlerFlags & gBitTable [ BATTLE_PARTNER ( battlerAtk ) ] ) )
basePower * = 2 ;
break ;
}
if ( basePower = = 0 )
basePower = 1 ;
return basePower ;
}
static u32 CalcMoveBasePowerAfterModifiers ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType )
{
u32 i ;
u32 holdEffectAtk , holdEffectParamAtk ;
u16 basePower = CalcMoveBasePower ( move , battlerAtk , battlerDef ) ;
u16 holdEffectModifier ;
u16 modifier = UQ_4_12 ( 1.0 ) ;
// 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 :
if ( moveType = = TYPE_STEEL | | moveType = = TYPE_ROCK | | moveType = = TYPE_GROUND )
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 :
if ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
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 ;
2018-07-14 22:56:03 +02:00
}
// field abilities
if ( ( ABILITY_ON_FIELD ( ABILITY_DARK_AURA ) & & moveType = = TYPE_DARK )
| | ( ABILITY_ON_FIELD ( ABILITY_FAIRY_AURA ) & & moveType = = TYPE_FAIRY ) )
{
if ( ABILITY_ON_FIELD ( ABILITY_AURA_BREAK ) )
MulModifier ( & modifier , UQ_4_12 ( 0.75 ) ) ;
else
MulModifier ( & modifier , UQ_4_12 ( 1.25 ) ) ;
}
// 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 ;
}
}
// target's abilities
switch ( GetBattlerAbility ( battlerDef ) )
{
case ABILITY_HEATPROOF :
case ABILITY_WATER_BUBBLE :
if ( moveType = = TYPE_FIRE )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case ABILITY_DRY_SKIN :
if ( moveType = = TYPE_FIRE )
MulModifier ( & modifier , UQ_4_12 ( 1.25 ) ) ;
break ;
case ABILITY_FLUFFY :
if ( IsMoveMakingContact ( move , battlerAtk ) )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
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 :
if ( ( gBattleMons [ battlerAtk ] . species = = SPECIES_LATIAS | | gBattleMons [ battlerAtk ] . species = = SPECIES_LATIOS ) & & ! ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER ) )
MulModifier ( & modifier , holdEffectModifier ) ;
break ;
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 ;
}
// 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 :
if ( gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerAtk ] . maxHP / 2 ) )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case EFFECT_VENOSHOCK :
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_PSN_ANY )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case EFFECT_RETALITATE :
// todo
break ;
case EFFECT_SOLARBEAM :
if ( WEATHER_HAS_EFFECT & & gBattleWeather & ( WEATHER_HAIL_ANY | WEATHER_SANDSTORM_ANY | WEATHER_RAIN_ANY ) )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case EFFECT_BULLDOZE :
case EFFECT_MAGNITUDE :
case EFFECT_EARTHQUAKE :
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & IsBattlerGrounded ( battlerDef ) )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
case EFFECT_KNOCK_OFF :
if ( gBattleMons [ battlerDef ] . item ! = ITEM_NONE & & GetBattlerAbility ( battlerDef ) ! = ABILITY_STICKY_HOLD )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
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 ) ) ;
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & moveType = = TYPE_GRASS & & IsBattlerGrounded ( battlerAtk ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
if ( gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN & & moveType = = TYPE_DRAGON & & IsBattlerGrounded ( battlerDef ) )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
if ( gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN & & moveType = = TYPE_ELECTRIC & & IsBattlerGrounded ( battlerAtk ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
if ( gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN & & moveType = = TYPE_PSYCHIC & & IsBattlerGrounded ( battlerAtk ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
return ApplyModifier ( modifier , basePower ) ;
}
static u32 CalcAttackStat ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , bool32 isCrit )
{
u8 atkStage ;
u32 atkStat ;
u16 modifier ;
if ( gBattleMoves [ move ] . effect = = EFFECT_FOUL_PLAY )
{
if ( IS_MOVE_PHYSICAL ( move ) )
atkStat = gBattleMons [ battlerDef ] . attack ;
else
atkStat = gBattleMons [ battlerDef ] . spAttack ;
atkStage = gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] ;
}
else
{
if ( IS_MOVE_PHYSICAL ( move ) )
atkStat = gBattleMons [ battlerAtk ] . attack ;
else
atkStat = gBattleMons [ battlerAtk ] . spAttack ;
atkStage = gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] ;
}
// critical hits ignore attack stat's stage drops
if ( isCrit & & atkStage < 6 )
atkStage = 6 ;
// pokemon with unaware ignore attack stat changes while taking damage
if ( GetBattlerAbility ( battlerDef ) = = ABILITY_UNAWARE )
atkStage = 6 ;
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 :
if ( IS_MOVE_SPECIAL ( move ) & & WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SUN_ANY )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_DEFEATIST :
if ( gBattleMons [ battlerAtk ] . hp < = ( gBattleMons [ battlerDef ] . maxHP / 2 ) )
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 :
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_CHERRIM & & WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SUN_ANY )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_HUSTLE :
if ( IS_MOVE_PHYSICAL ( move ) )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
// target's abilities
switch ( GetBattlerAbility ( battlerDef ) )
{
case ABILITY_THICK_FAT :
if ( moveType = = TYPE_FIRE | | moveType = = TYPE_ICE )
MulModifier ( & modifier , UQ_4_12 ( 0.5 ) ) ;
break ;
}
// ally's abilities
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) )
{
switch ( GetBattlerAbility ( BATTLE_PARTNER ( battlerAtk ) ) )
{
case ABILITY_FLOWER_GIFT :
if ( gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . species = = SPECIES_CHERRIM )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
}
// attacker's hold effect
switch ( GetBattlerHoldEffect ( battlerAtk , TRUE ) )
{
case HOLD_EFFECT_THICK_CLUB :
if ( ( gBattleMons [ battlerAtk ] . species = = SPECIES_CUBONE | | gBattleMons [ battlerAtk ] . species = = SPECIES_MAROWAK ) & & IS_MOVE_PHYSICAL ( move ) )
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 ;
}
return ApplyModifier ( modifier , atkStat ) ;
}
static u32 CalcDefenseStat ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , bool32 isCrit )
{
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
if ( isCrit & & defStage > 6 )
defStage = 6 ;
// pokemon with unaware ignore defense stat changes while dealing damage
if ( GetBattlerAbility ( battlerAtk ) = = ABILITY_UNAWARE )
defStage = 6 ;
// certain moves also ignore stat changes
if ( gBattleMoves [ move ] . flags & FLAG_STAT_STAGES_IGNORED )
defStage = 6 ;
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 )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_FUR_COAT :
if ( usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 2.0 ) ) ;
break ;
case ABILITY_GRASS_PELT :
if ( gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN & & usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
case ABILITY_FLOWER_GIFT :
if ( gBattleMons [ battlerDef ] . species = = SPECIES_CHERRIM & & WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SUN_ANY & & ! usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
// ally's abilities
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerDef ) ) )
{
switch ( GetBattlerAbility ( BATTLE_PARTNER ( battlerDef ) ) )
{
case ABILITY_FLOWER_GIFT :
if ( gBattleMons [ BATTLE_PARTNER ( battlerDef ) ] . species = = SPECIES_CHERRIM & & ! usesDefStat )
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 :
// todo
break ;
case HOLD_EFFECT_ASSAULT_VEST :
if ( ! usesDefStat )
MulModifier ( & modifier , UQ_4_12 ( 1.5 ) ) ;
break ;
}
return ApplyModifier ( modifier , defStat ) ;
}
static u32 CalcFinalDmg ( u32 dmg , u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , u16 typeEffectivenessModifier , bool32 isCrit )
{
u32 abilityAtk = GetBattlerAbility ( battlerAtk ) ;
u32 abilityDef = GetBattlerAbility ( battlerDef ) ;
u32 defSide = GET_BATTLER_SIDE ( battlerDef ) ;
u16 finalModifier = UQ_4_12 ( 1.0 ) ;
// 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 )
dmg = ApplyModifier ( UQ_4_12 ( 1.5 ) , dmg ) ;
// check burn
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_BURN & & gBattleMoves [ move ] . effect ! = EFFECT_FACADE & & abilityAtk ! = ABILITY_GUTS )
dmg = ApplyModifier ( UQ_4_12 ( 0.5 ) , dmg ) ;
// check sunny/rain weather
if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_RAIN_ANY )
{
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 ) ;
}
else if ( WEATHER_HAS_EFFECT & & gBattleWeather & WEATHER_SUN_ANY )
{
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
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 ) )
{
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 ;
}
// target's abilities
switch ( abilityDef )
{
case ABILITY_MULTISCALE :
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 :
// todo
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 ) )
{
// berries reducing dmg
}
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 ) ) ;
dmg = ApplyModifier ( finalModifier , dmg ) ;
if ( dmg = = 0 )
dmg = 1 ;
return dmg ;
}
s32 CalculateMoveDamage ( u16 move , u8 battlerAtk , u8 battlerDef , u8 moveType , s32 fixedBasePower , bool32 isCrit , bool32 randomFactor )
{
s32 dmg ;
u16 finalModifier , typeEffectivenessModifier ;
typeEffectivenessModifier = CalcTypeEffectivenessMultiplier ( move , moveType , battlerAtk , battlerDef , randomFactor ) ;
// 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
gBattleMovePower = CalcMoveBasePowerAfterModifiers ( move , battlerAtk , battlerDef , moveType ) ;
// long dmg basic formula
dmg = ( ( gBattleMons [ battlerAtk ] . level * 2 ) / 5 ) + 2 ;
dmg * = gBattleMovePower ;
dmg * = CalcAttackStat ( move , battlerAtk , battlerDef , moveType , isCrit ) ;
dmg / = CalcDefenseStat ( move , battlerAtk , battlerDef , moveType , isCrit ) ;
dmg = ( dmg / 50 ) + 2 ;
// Calculate final modifiers.
dmg = CalcFinalDmg ( dmg , move , battlerAtk , battlerDef , moveType , typeEffectivenessModifier , isCrit ) ;
// Add a random factor.
if ( randomFactor )
{
dmg * = 100 - ( Random ( ) % 16 ) ;
dmg / = 100 ;
}
if ( dmg = = 0 )
dmg = 1 ;
return dmg ;
}
2018-07-22 19:34:13 +02:00
static inline void MulByTypeEffectiveness ( u16 * modifier , u16 move , u8 moveType , u8 battlerDef , u8 defType , u8 atkAblity )
2018-07-14 22:56:03 +02:00
{
u16 mod = sTypeEffectivenessTable [ moveType ] [ defType ] ;
if ( ( moveType = = TYPE_FIGHTING | | moveType = = TYPE_NORMAL ) & & defType = = TYPE_GHOST & & gBattleMons [ battlerDef ] . status2 & STATUS2_FORESIGHT )
mod = UQ_4_12 ( 1.0 ) ;
2018-07-22 19:34:13 +02:00
if ( ( moveType = = TYPE_FIGHTING | | moveType = = TYPE_NORMAL ) & & defType = = TYPE_GHOST & & atkAblity = = ABILITY_SCRAPPY )
mod = UQ_4_12 ( 1.0 ) ;
2018-07-14 22:56:03 +02:00
if ( moveType = = TYPE_PSYCHIC & & defType = = TYPE_DARK & & gStatuses3 [ battlerDef ] & STATUS3_MIRACLE_EYED )
mod = UQ_4_12 ( 1.0 ) ;
if ( move = = MOVE_FREEZE_DRY & & defType = = TYPE_WATER )
mod = UQ_4_12 ( 2.0 ) ;
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-07-14 22:56:03 +02:00
u16 CalcTypeEffectivenessMultiplier ( u16 move , u8 moveType , u8 battlerAtk , u8 battlerDef , bool32 recordAbilities )
2018-07-14 19:29:25 +02:00
{
2018-07-14 22:56:03 +02:00
u16 modifier = UQ_4_12 ( 1.0 ) ;
if ( move ! = MOVE_STRUGGLE & & moveType ! = TYPE_MYSTERY )
{
2018-07-22 19:34:13 +02:00
u32 atkAbility = GetBattlerAbility ( battlerAtk ) ;
MulByTypeEffectiveness ( & modifier , move , moveType , battlerDef , gBattleMons [ battlerDef ] . type1 , atkAbility ) ;
2018-07-14 22:56:03 +02:00
if ( gBattleMons [ battlerDef ] . type2 ! = gBattleMons [ battlerDef ] . type1 )
2018-07-22 19:34:13 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , battlerDef , gBattleMons [ battlerDef ] . type2 , atkAbility ) ;
2018-07-14 22:56:03 +02:00
if ( moveType = = TYPE_GROUND & & ! IsBattlerGrounded ( battlerDef ) )
{
modifier = UQ_4_12 ( 0.0 ) ;
if ( recordAbilities & & GetBattlerAbility ( battlerDef ) = = ABILITY_LEVITATE )
{
gLastUsedAbility = ABILITY_LEVITATE ;
gMoveResultFlags | = ( MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE ) ;
gLastLandedMoves [ battlerDef ] = 0 ;
gBattleCommunication [ 6 ] = moveType ;
RecordAbilityBattle ( battlerDef , ABILITY_LEVITATE ) ;
}
}
if ( GetBattlerAbility ( battlerDef ) = = ABILITY_WONDER_GUARD & & modifier < = UQ_4_12 ( 1.0 ) & & gBattleMoves [ move ] . power )
{
modifier = UQ_4_12 ( 0.0 ) ;
if ( recordAbilities )
{
gLastUsedAbility = ABILITY_WONDER_GUARD ;
gMoveResultFlags | = MOVE_RESULT_MISSED ;
gLastLandedMoves [ battlerDef ] = 0 ;
gBattleCommunication [ 6 ] = 3 ;
RecordAbilityBattle ( battlerDef , ABILITY_WONDER_GUARD ) ;
}
}
}
2018-07-15 12:39:07 +02:00
UpdateMoveResultFlags ( modifier ) ;
return modifier ;
}
u16 CalcPartyMonTypeEffectivenessMultiplier ( u16 move , u16 speciesDef , u8 abilityDef )
{
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
{
2018-07-22 19:34:13 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , 0 , gBaseStats [ speciesDef ] . type1 , ABILITY_NONE ) ;
2018-07-15 12:39:07 +02:00
if ( gBaseStats [ speciesDef ] . type2 ! = gBaseStats [ speciesDef ] . type1 )
2018-07-22 19:34:13 +02:00
MulByTypeEffectiveness ( & modifier , move , moveType , 0 , gBaseStats [ speciesDef ] . type2 , ABILITY_NONE ) ;
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 )
{
return sTypeEffectivenessTable [ atkType ] [ defType ] ;
}
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 ;
}