2017-02-02 05:15:38 +01:00
# include "global.h"
2018-12-09 13:12:02 +01:00
# include "alloc.h"
2017-02-04 03:34:56 +01:00
# include "battle.h"
2019-03-31 19:15:39 +02:00
# include "battle_anim.h"
2018-11-14 01:01:50 +01:00
# include "battle_ai_script_commands.h"
# include "battle_factory.h"
2018-02-08 00:00:25 +01:00
# include "battle_setup.h"
2019-04-04 23:53:06 +02:00
# include "data.h"
2017-09-05 09:41:48 +02:00
# include "item.h"
2018-11-14 01:01:50 +01:00
# include "pokemon.h"
# include "random.h"
# include "recorded_battle.h"
2018-11-11 16:44:27 +01:00
# include "util.h"
# include "constants/abilities.h"
2018-11-14 01:01:50 +01:00
# include "constants/battle_ai.h"
2017-12-05 18:55:48 +01:00
# include "constants/battle_move_effects.h"
2017-12-11 19:27:51 +01:00
# include "constants/moves.h"
2018-11-14 01:01:50 +01:00
# include "constants/species.h"
2017-02-02 05:15:38 +01:00
2017-09-05 09:41:48 +02:00
# define AI_ACTION_DONE 0x0001
# define AI_ACTION_FLEE 0x0002
# define AI_ACTION_WATCH 0x0004
# define AI_ACTION_DO_NOT_ATTACK 0x0008
2017-02-04 03:34:56 +01:00
# define AI_ACTION_UNK5 0x0010
# define AI_ACTION_UNK6 0x0020
# define AI_ACTION_UNK7 0x0040
# define AI_ACTION_UNK8 0x0080
2017-09-05 09:41:48 +02:00
# define AI_THINKING_STRUCT ((struct AI_ThinkingStruct *)(gBattleResources->ai))
# define BATTLE_HISTORY ((struct BattleHistory *)(gBattleResources->battleHistory))
2017-02-04 03:34:56 +01:00
// AI states
enum
{
AIState_SettingUp ,
AIState_Processing ,
AIState_FinishedProcessing ,
AIState_DoNotProcess
} ;
/*
gAIScriptPtr is a pointer to the next battle AI cmd command to read .
when a command finishes processing , gAIScriptPtr is incremented by
the number of bytes that the current command had reserved for arguments
in order to read the next command correctly . refer to battle_ai_scripts . s for the
AI scripts .
*/
2018-06-17 16:48:58 +02:00
extern const u8 * const gBattleAI_ScriptsTable [ ] ;
2017-09-05 09:41:48 +02:00
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Singles ( void ) ;
static u8 ChooseMoveOrAction_Doubles ( void ) ;
2017-09-05 09:41:48 +02:00
static void RecordLastUsedMoveByTarget ( void ) ;
static void BattleAI_DoAIProcessing ( void ) ;
2017-09-17 14:10:32 +02:00
static void AIStackPushVar ( const u8 * ) ;
2017-09-05 09:41:48 +02:00
static bool8 AIStackPop ( void ) ;
2019-06-11 10:45:12 +02:00
static s32 CountUsablePartyMons ( u8 battlerId ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_random_less_than ( void ) ;
static void BattleAICmd_if_random_greater_than ( void ) ;
static void BattleAICmd_if_random_equal ( void ) ;
static void BattleAICmd_if_random_not_equal ( void ) ;
static void BattleAICmd_score ( void ) ;
static void BattleAICmd_if_hp_less_than ( void ) ;
static void BattleAICmd_if_hp_more_than ( void ) ;
static void BattleAICmd_if_hp_equal ( void ) ;
static void BattleAICmd_if_hp_not_equal ( void ) ;
static void BattleAICmd_if_status ( void ) ;
static void BattleAICmd_if_not_status ( void ) ;
static void BattleAICmd_if_status2 ( void ) ;
static void BattleAICmd_if_not_status2 ( void ) ;
static void BattleAICmd_if_status3 ( void ) ;
static void BattleAICmd_if_not_status3 ( void ) ;
static void BattleAICmd_if_side_affecting ( void ) ;
static void BattleAICmd_if_not_side_affecting ( void ) ;
static void BattleAICmd_if_less_than ( void ) ;
static void BattleAICmd_if_more_than ( void ) ;
static void BattleAICmd_if_equal ( void ) ;
static void BattleAICmd_if_not_equal ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_less_than_ptr ( void ) ;
static void BattleAICmd_if_more_than_ptr ( void ) ;
static void BattleAICmd_if_equal_ptr ( void ) ;
static void BattleAICmd_if_not_equal_ptr ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_move ( void ) ;
static void BattleAICmd_if_not_move ( void ) ;
static void BattleAICmd_if_in_bytes ( void ) ;
static void BattleAICmd_if_not_in_bytes ( void ) ;
2017-10-09 13:41:07 +02:00
static void BattleAICmd_if_in_hwords ( void ) ;
static void BattleAICmd_if_not_in_hwords ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_user_has_attacking_move ( void ) ;
static void BattleAICmd_if_user_has_no_attacking_moves ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_turn_count ( void ) ;
static void BattleAICmd_get_type ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_get_considered_move_power ( void ) ;
static void BattleAICmd_get_how_powerful_move_is ( void ) ;
2018-06-17 16:48:58 +02:00
static void BattleAICmd_get_last_used_battler_move ( void ) ;
2019-05-20 10:10:00 +02:00
static void BattleAICmd_if_equal_u32 ( void ) ;
static void BattleAICmd_if_not_equal_u32 ( void ) ;
2019-02-16 18:23:56 +01:00
static void BattleAICmd_if_user_goes ( void ) ;
static void BattleAICmd_if_cant_use_belch ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_2A ( void ) ;
static void BattleAICmd_nullsub_2B ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_count_usable_party_mons ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_considered_move ( void ) ;
static void BattleAICmd_get_considered_move_effect ( void ) ;
static void BattleAICmd_get_ability ( void ) ;
static void BattleAICmd_get_highest_type_effectiveness ( void ) ;
static void BattleAICmd_if_type_effectiveness ( void ) ;
static void BattleAICmd_nullsub_32 ( void ) ;
static void BattleAICmd_nullsub_33 ( void ) ;
static void BattleAICmd_if_status_in_party ( void ) ;
static void BattleAICmd_if_status_not_in_party ( void ) ;
static void BattleAICmd_get_weather ( void ) ;
static void BattleAICmd_if_effect ( void ) ;
static void BattleAICmd_if_not_effect ( void ) ;
static void BattleAICmd_if_stat_level_less_than ( void ) ;
static void BattleAICmd_if_stat_level_more_than ( void ) ;
static void BattleAICmd_if_stat_level_equal ( void ) ;
static void BattleAICmd_if_stat_level_not_equal ( void ) ;
static void BattleAICmd_if_can_faint ( void ) ;
static void BattleAICmd_if_cant_faint ( void ) ;
static void BattleAICmd_if_has_move ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_doesnt_have_move ( void ) ;
static void BattleAICmd_if_has_move_with_effect ( void ) ;
static void BattleAICmd_if_doesnt_have_move_with_effect ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_any_move_disabled_or_encored ( void ) ;
static void BattleAICmd_if_curr_move_disabled_or_encored ( void ) ;
static void BattleAICmd_flee ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_random_safari_flee ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_watch ( void ) ;
static void BattleAICmd_get_hold_effect ( void ) ;
static void BattleAICmd_get_gender ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_is_first_turn_for ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_stockpile_count ( void ) ;
static void BattleAICmd_is_double_battle ( void ) ;
static void BattleAICmd_get_used_held_item ( void ) ;
static void BattleAICmd_get_move_type_from_result ( void ) ;
static void BattleAICmd_get_move_power_from_result ( void ) ;
static void BattleAICmd_get_move_effect_from_result ( void ) ;
static void BattleAICmd_get_protect_count ( void ) ;
2018-07-14 12:54:12 +02:00
static void BattleAICmd_if_move_flag ( void ) ;
2018-07-14 16:41:14 +02:00
static void BattleAICmd_if_field_status ( void ) ;
2018-08-11 12:16:00 +02:00
static void BattleAICmd_get_move_accuracy ( void ) ;
static void BattleAICmd_call_if_eq ( void ) ;
static void BattleAICmd_call_if_move_flag ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_57 ( void ) ;
static void BattleAICmd_call ( void ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_goto ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAICmd_end ( void ) ;
static void BattleAICmd_if_level_cond ( void ) ;
static void BattleAICmd_if_target_taunted ( void ) ;
static void BattleAICmd_if_target_not_taunted ( void ) ;
static void BattleAICmd_check_ability ( void ) ;
static void BattleAICmd_is_of_type ( void ) ;
static void BattleAICmd_if_target_is_ally ( void ) ;
static void BattleAICmd_if_flash_fired ( void ) ;
static void BattleAICmd_if_holds_item ( void ) ;
2018-09-01 17:36:09 +02:00
static void BattleAICmd_get_ally_chosen_move ( void ) ;
static void BattleAICmd_if_has_no_attacking_moves ( void ) ;
2018-09-02 15:50:18 +02:00
static void BattleAICmd_get_hazards_count ( void ) ;
static void BattleAICmd_if_doesnt_hold_berry ( void ) ;
2018-12-02 23:50:51 +01:00
static void BattleAICmd_if_share_type ( void ) ;
static void BattleAICmd_if_cant_use_last_resort ( void ) ;
2019-02-09 13:21:32 +01:00
static void BattleAICmd_if_has_move_with_split ( void ) ;
static void BattleAICmd_if_has_no_move_with_split ( void ) ;
2019-02-09 16:45:02 +01:00
static void BattleAICmd_if_physical_moves_unusable ( void ) ;
2019-02-16 14:54:17 +01:00
static void BattleAICmd_if_ai_can_go_down ( void ) ;
2019-05-20 10:10:00 +02:00
static void BattleAICmd_if_has_move_with_type ( void ) ;
2019-05-20 12:03:00 +02:00
static void BattleAICmd_if_no_move_used ( void ) ;
2019-05-23 11:41:35 +02:00
static void BattleAICmd_if_has_move_with_flag ( void ) ;
2017-09-05 09:41:48 +02:00
// ewram
2017-09-17 14:10:32 +02:00
EWRAM_DATA const u8 * gAIScriptPtr = NULL ;
2018-02-06 23:09:39 +01:00
EWRAM_DATA static u8 sBattler_AI = 0 ;
2017-09-05 09:41:48 +02:00
// const rom data
2017-02-02 05:15:38 +01:00
typedef void ( * BattleAICmdFunc ) ( void ) ;
2017-09-05 09:41:48 +02:00
static const BattleAICmdFunc sBattleAICmdTable [ ] =
{
2018-06-17 16:48:58 +02:00
BattleAICmd_if_random_less_than , // 0x0
BattleAICmd_if_random_greater_than , // 0x1
BattleAICmd_if_random_equal , // 0x2
BattleAICmd_if_random_not_equal , // 0x3
BattleAICmd_score , // 0x4
BattleAICmd_if_hp_less_than , // 0x5
BattleAICmd_if_hp_more_than , // 0x6
BattleAICmd_if_hp_equal , // 0x7
BattleAICmd_if_hp_not_equal , // 0x8
BattleAICmd_if_status , // 0x9
BattleAICmd_if_not_status , // 0xA
BattleAICmd_if_status2 , // 0xB
BattleAICmd_if_not_status2 , // 0xC
BattleAICmd_if_status3 , // 0xD
BattleAICmd_if_not_status3 , // 0xE
BattleAICmd_if_side_affecting , // 0xF
BattleAICmd_if_not_side_affecting , // 0x10
BattleAICmd_if_less_than , // 0x11
BattleAICmd_if_more_than , // 0x12
BattleAICmd_if_equal , // 0x13
BattleAICmd_if_not_equal , // 0x14
BattleAICmd_if_less_than_ptr , // 0x15
BattleAICmd_if_more_than_ptr , // 0x16
BattleAICmd_if_equal_ptr , // 0x17
BattleAICmd_if_not_equal_ptr , // 0x18
BattleAICmd_if_move , // 0x19
BattleAICmd_if_not_move , // 0x1A
BattleAICmd_if_in_bytes , // 0x1B
BattleAICmd_if_not_in_bytes , // 0x1C
BattleAICmd_if_in_hwords , // 0x1D
BattleAICmd_if_not_in_hwords , // 0x1E
BattleAICmd_if_user_has_attacking_move , // 0x1F
BattleAICmd_if_user_has_no_attacking_moves , // 0x20
BattleAICmd_get_turn_count , // 0x21
BattleAICmd_get_type , // 0x22
BattleAICmd_get_considered_move_power , // 0x23
BattleAICmd_get_how_powerful_move_is , // 0x24
BattleAICmd_get_last_used_battler_move , // 0x25
2019-05-20 10:10:00 +02:00
BattleAICmd_if_equal_u32 , // 0x26
BattleAICmd_if_not_equal_u32 , // 0x27
2018-06-17 16:48:58 +02:00
BattleAICmd_if_user_goes , // 0x28
2019-02-16 18:23:56 +01:00
BattleAICmd_if_cant_use_belch , // 0x29
2018-06-17 16:48:58 +02:00
BattleAICmd_nullsub_2A , // 0x2A
BattleAICmd_nullsub_2B , // 0x2B
BattleAICmd_count_usable_party_mons , // 0x2C
BattleAICmd_get_considered_move , // 0x2D
BattleAICmd_get_considered_move_effect , // 0x2E
BattleAICmd_get_ability , // 0x2F
BattleAICmd_get_highest_type_effectiveness , // 0x30
BattleAICmd_if_type_effectiveness , // 0x31
BattleAICmd_nullsub_32 , // 0x32
BattleAICmd_nullsub_33 , // 0x33
BattleAICmd_if_status_in_party , // 0x34
BattleAICmd_if_status_not_in_party , // 0x35
BattleAICmd_get_weather , // 0x36
BattleAICmd_if_effect , // 0x37
BattleAICmd_if_not_effect , // 0x38
BattleAICmd_if_stat_level_less_than , // 0x39
BattleAICmd_if_stat_level_more_than , // 0x3A
BattleAICmd_if_stat_level_equal , // 0x3B
BattleAICmd_if_stat_level_not_equal , // 0x3C
BattleAICmd_if_can_faint , // 0x3D
BattleAICmd_if_cant_faint , // 0x3E
BattleAICmd_if_has_move , // 0x3F
BattleAICmd_if_doesnt_have_move , // 0x40
BattleAICmd_if_has_move_with_effect , // 0x41
BattleAICmd_if_doesnt_have_move_with_effect , // 0x42
2017-09-05 09:41:48 +02:00
BattleAICmd_if_any_move_disabled_or_encored , // 0x43
BattleAICmd_if_curr_move_disabled_or_encored , // 0x44
2018-06-17 16:48:58 +02:00
BattleAICmd_flee , // 0x45
BattleAICmd_if_random_safari_flee , // 0x46
BattleAICmd_watch , // 0x47
BattleAICmd_get_hold_effect , // 0x48
BattleAICmd_get_gender , // 0x49
BattleAICmd_is_first_turn_for , // 0x4A
BattleAICmd_get_stockpile_count , // 0x4B
BattleAICmd_is_double_battle , // 0x4C
BattleAICmd_get_used_held_item , // 0x4D
BattleAICmd_get_move_type_from_result , // 0x4E
BattleAICmd_get_move_power_from_result , // 0x4F
BattleAICmd_get_move_effect_from_result , // 0x50
BattleAICmd_get_protect_count , // 0x51
2018-07-14 12:54:12 +02:00
BattleAICmd_if_move_flag , // 0x52
2018-07-14 16:41:14 +02:00
BattleAICmd_if_field_status , // 0x53
2018-08-11 12:16:00 +02:00
BattleAICmd_get_move_accuracy , // 0x54
BattleAICmd_call_if_eq , // 0x55
BattleAICmd_call_if_move_flag , // 0x56
2018-06-17 16:48:58 +02:00
BattleAICmd_nullsub_57 , // 0x57
BattleAICmd_call , // 0x58
BattleAICmd_goto , // 0x59
BattleAICmd_end , // 0x5A
BattleAICmd_if_level_cond , // 0x5B
BattleAICmd_if_target_taunted , // 0x5C
BattleAICmd_if_target_not_taunted , // 0x5D
BattleAICmd_if_target_is_ally , // 0x5E
BattleAICmd_is_of_type , // 0x5F
BattleAICmd_check_ability , // 0x60
BattleAICmd_if_flash_fired , // 0x61
BattleAICmd_if_holds_item , // 0x62
2018-09-01 17:36:09 +02:00
BattleAICmd_get_ally_chosen_move , // 0x63
BattleAICmd_if_has_no_attacking_moves , // 0x64
2018-09-02 15:50:18 +02:00
BattleAICmd_get_hazards_count , // 0x65
BattleAICmd_if_doesnt_hold_berry , // 0x66
2018-12-02 23:50:51 +01:00
BattleAICmd_if_share_type , // 0x67
BattleAICmd_if_cant_use_last_resort , // 0x68
2019-02-09 13:21:32 +01:00
BattleAICmd_if_has_move_with_split , // 0x69
BattleAICmd_if_has_no_move_with_split , // 0x6A
2019-02-09 16:45:02 +01:00
BattleAICmd_if_physical_moves_unusable , // 0x6B
2019-02-16 14:54:17 +01:00
BattleAICmd_if_ai_can_go_down , // 0x6C
2019-05-20 10:10:00 +02:00
BattleAICmd_if_has_move_with_type , // 0x6D
2019-05-20 12:03:00 +02:00
BattleAICmd_if_no_move_used , // 0x6E
2019-05-23 11:41:35 +02:00
BattleAICmd_if_has_move_with_flag , // 0x6F
2017-09-05 09:41:48 +02:00
} ;
2017-02-02 05:15:38 +01:00
2017-09-05 09:41:48 +02:00
static const u16 sDiscouragedPowerfulMoveEffects [ ] =
{
EFFECT_EXPLOSION ,
EFFECT_DREAM_EATER ,
EFFECT_RECHARGE ,
EFFECT_SKULL_BASH ,
EFFECT_SOLARBEAM ,
EFFECT_SPIT_UP ,
EFFECT_FOCUS_PUNCH ,
EFFECT_SUPERPOWER ,
EFFECT_ERUPTION ,
EFFECT_OVERHEAT ,
0xFFFF
} ;
2017-02-02 05:15:38 +01:00
2018-06-17 16:48:58 +02:00
// code
2018-12-22 20:57:12 +01:00
void BattleAI_SetupItems ( void )
2017-02-02 05:15:38 +01:00
{
s32 i ;
2018-06-17 16:48:58 +02:00
u8 * data = ( u8 * ) BATTLE_HISTORY ;
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
for ( i = 0 ; i < sizeof ( struct BattleHistory ) ; i + + )
2017-02-02 05:15:38 +01:00
data [ i ] = 0 ;
2018-06-17 16:48:58 +02:00
// Items are allowed to use in ONLY trainer battles.
if ( ( gBattleTypeFlags & BATTLE_TYPE_TRAINER )
& & ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_BATTLE_TOWER
| BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_x2000000 )
)
)
2017-02-02 05:15:38 +01:00
{
for ( i = 0 ; i < 4 ; i + + )
{
2017-09-05 09:41:48 +02:00
if ( gTrainers [ gTrainerBattleOpponent_A ] . items [ i ] ! = 0 )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > trainerItems [ BATTLE_HISTORY - > itemsNo ] = gTrainers [ gTrainerBattleOpponent_A ] . items [ i ] ;
BATTLE_HISTORY - > itemsNo + + ;
2017-02-02 05:15:38 +01:00
}
}
}
2018-12-22 20:57:12 +01:00
}
void BattleAI_SetupFlags ( void )
{
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
AI_THINKING_STRUCT - > aiFlags = GetAiScriptsInRecordedBattle ( ) ;
else if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_SAFARI ;
else if ( gBattleTypeFlags & BATTLE_TYPE_ROAMER )
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_ROAMING ;
else if ( gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE )
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_FIRST_BATTLE ;
else if ( gBattleTypeFlags & BATTLE_TYPE_FACTORY )
AI_THINKING_STRUCT - > aiFlags = GetAiScriptsInBattleFactory ( ) ;
else if ( gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE ) )
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_CHECK_VIABILITY | AI_SCRIPT_TRY_TO_FAINT ;
else if ( gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS )
AI_THINKING_STRUCT - > aiFlags = gTrainers [ gTrainerBattleOpponent_A ] . aiFlags | gTrainers [ gTrainerBattleOpponent_B ] . aiFlags ;
else
AI_THINKING_STRUCT - > aiFlags = gTrainers [ gTrainerBattleOpponent_A ] . aiFlags ;
2017-09-04 21:43:13 +02:00
2018-12-22 21:43:21 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS ) | | gTrainers [ gTrainerBattleOpponent_A ] . doubleBattle )
2018-12-22 20:57:12 +01:00
AI_THINKING_STRUCT - > aiFlags | = AI_SCRIPT_DOUBLE_BATTLE ; // Act smart in doubles and don't attack your partner.
2017-02-02 05:15:38 +01:00
}
2017-09-05 09:41:48 +02:00
void BattleAI_SetupAIData ( u8 defaultScoreMoves )
2017-02-02 05:15:38 +01:00
{
s32 i ;
2017-09-05 09:41:48 +02:00
u8 moveLimitations ;
2017-02-04 03:34:56 +01:00
2018-12-22 20:57:12 +01:00
// Clear AI data but preserve the flags.
u32 flags = AI_THINKING_STRUCT - > aiFlags ;
memset ( AI_THINKING_STRUCT , 0 , sizeof ( struct AI_ThinkingStruct ) ) ;
AI_THINKING_STRUCT - > aiFlags = flags ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Conditional score reset, unlike Ruby.
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-05 09:41:48 +02:00
if ( defaultScoreMoves & 1 )
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ i ] = 100 ;
2017-02-02 05:15:38 +01:00
else
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ i ] = 0 ;
2018-06-17 16:48:58 +02:00
2017-09-05 09:41:48 +02:00
defaultScoreMoves > > = 1 ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
2018-02-06 02:46:59 +01:00
moveLimitations = CheckMoveLimitations ( gActiveBattler , 0 , 0xFF ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Ignore moves that aren't possible to use.
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-05 09:41:48 +02:00
if ( gBitTable [ i ] & moveLimitations )
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ i ] = 0 ;
2017-09-05 09:41:48 +02:00
AI_THINKING_STRUCT - > simulatedRNG [ i ] = 100 - ( Random ( ) % 16 ) ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
2017-09-04 21:43:13 +02:00
gBattleResources - > AI_ScriptsStack - > size = 0 ;
2018-02-06 23:09:39 +01:00
sBattler_AI = gActiveBattler ;
2018-06-17 16:48:58 +02:00
// Decide a random target battlerId in doubles.
2017-09-05 09:41:48 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
2017-02-02 05:15:38 +01:00
{
2018-02-06 23:09:39 +01:00
gBattlerTarget = ( Random ( ) & BIT_FLANK ) + ( GetBattlerSide ( gActiveBattler ) ^ BIT_SIDE ) ;
if ( gAbsentBattlerFlags & gBitTable [ gBattlerTarget ] )
gBattlerTarget ^ = BIT_FLANK ;
2017-02-02 05:15:38 +01:00
}
2018-07-16 20:47:30 +02:00
// There's only one choice in single battles.
2017-02-02 05:15:38 +01:00
else
2017-12-30 16:04:31 +01:00
{
2018-02-06 23:09:39 +01:00
gBattlerTarget = sBattler_AI ^ BIT_SIDE ;
2017-12-30 16:04:31 +01:00
}
2017-02-02 05:15:38 +01:00
}
2017-09-05 09:41:48 +02:00
u8 BattleAI_ChooseMoveOrAction ( void )
2017-02-02 05:15:38 +01:00
{
2017-09-05 09:41:48 +02:00
u16 savedCurrentMove = gCurrentMove ;
2017-02-02 05:15:38 +01:00
u8 ret ;
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) )
2018-06-17 16:48:58 +02:00
ret = ChooseMoveOrAction_Singles ( ) ;
2017-02-02 05:15:38 +01:00
else
2018-06-17 16:48:58 +02:00
ret = ChooseMoveOrAction_Doubles ( ) ;
2017-02-04 03:34:56 +01:00
2017-09-05 09:41:48 +02:00
gCurrentMove = savedCurrentMove ;
2017-02-02 05:15:38 +01:00
return ret ;
}
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Singles ( void )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
u8 currentMoveArray [ 4 ] ;
u8 consideredMoveArray [ 4 ] ;
u8 numOfBestMoves ;
2017-02-02 05:15:38 +01:00
s32 i ;
2018-12-22 20:57:12 +01:00
u32 flags = AI_THINKING_STRUCT - > aiFlags ;
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
RecordLastUsedMoveByTarget ( ) ;
2017-02-04 03:34:56 +01:00
2018-12-22 20:57:12 +01:00
while ( flags ! = 0 )
2017-02-02 05:15:38 +01:00
{
2018-12-22 20:57:12 +01:00
if ( flags & 1 )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState = AIState_SettingUp ;
2017-02-02 05:15:38 +01:00
BattleAI_DoAIProcessing ( ) ;
}
2018-12-22 20:57:12 +01:00
flags > > = 1 ;
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiLogicId + + ;
AI_THINKING_STRUCT - > movesetIndex = 0 ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Check special AI actions.
2017-09-08 18:19:20 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_FLEE )
2018-06-17 16:48:58 +02:00
return AI_CHOICE_FLEE ;
2017-09-08 18:19:20 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_WATCH )
2018-06-17 16:48:58 +02:00
return AI_CHOICE_WATCH ;
2017-02-04 03:34:56 +01:00
2019-06-11 10:45:12 +02:00
// Consider switching if all moves are worthless to use.
if ( AI_THINKING_STRUCT - > aiFlags & ( AI_SCRIPT_CHECK_VIABILITY | AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_TRY_TO_FAINT | AI_SCRIPT_PREFER_BATON_PASS )
& & CountUsablePartyMons ( sBattler_AI ) > = 1
& & gBattleMons [ sBattler_AI ] . hp > = gBattleMons [ sBattler_AI ] . maxHP / 2
& & ! ( gBattleTypeFlags & BATTLE_TYPE_PALACE ) )
{
s32 cap = AI_THINKING_STRUCT - > aiFlags & ( AI_SCRIPT_CHECK_VIABILITY ) ? 95 : 93 ;
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
{
if ( AI_THINKING_STRUCT - > score [ i ] > cap )
break ;
}
gActiveBattler = sBattler_AI ;
if ( i = = MAX_MON_MOVES & & GetMostSuitableMonToSwitchInto ( ) ! = PARTY_SIZE )
{
AI_THINKING_STRUCT - > switchMon = TRUE ;
return AI_CHOICE_SWITCH ;
}
}
2017-02-04 03:34:56 +01:00
numOfBestMoves = 1 ;
currentMoveArray [ 0 ] = AI_THINKING_STRUCT - > score [ 0 ] ;
consideredMoveArray [ 0 ] = 0 ;
2018-12-25 18:50:15 +01:00
for ( i = 1 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
if ( gBattleMons [ sBattler_AI ] . moves [ i ] ! = MOVE_NONE )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
// In ruby, the order of these if statements is reversed.
2017-02-04 03:34:56 +01:00
if ( currentMoveArray [ 0 ] = = AI_THINKING_STRUCT - > score [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
currentMoveArray [ numOfBestMoves ] = AI_THINKING_STRUCT - > score [ i ] ;
consideredMoveArray [ numOfBestMoves + + ] = i ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
if ( currentMoveArray [ 0 ] < AI_THINKING_STRUCT - > score [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
numOfBestMoves = 1 ;
currentMoveArray [ 0 ] = AI_THINKING_STRUCT - > score [ i ] ;
consideredMoveArray [ 0 ] = i ;
2017-02-02 05:15:38 +01:00
}
}
}
2017-02-04 03:34:56 +01:00
return consideredMoveArray [ Random ( ) % numOfBestMoves ] ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Doubles ( void )
2017-02-02 05:15:38 +01:00
{
s32 i ;
s32 j ;
2018-12-22 20:57:12 +01:00
u32 flags ;
2017-09-08 18:19:20 +02:00
s16 bestMovePointsForTarget [ 4 ] ;
s8 mostViableTargetsArray [ 4 ] ;
u8 actionOrMoveIndex [ 4 ] ;
u8 mostViableMovesScores [ 4 ] ;
u8 mostViableMovesIndices [ 4 ] ;
s32 mostViableTargetsNo ;
s32 mostViableMovesNo ;
2017-10-09 13:41:07 +02:00
s16 mostMovePoints ;
2017-09-08 18:19:20 +02:00
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2017-02-02 05:15:38 +01:00
{
2018-02-06 23:09:39 +01:00
if ( i = = sBattler_AI | | gBattleMons [ i ] . hp = = 0 )
2017-02-02 05:15:38 +01:00
{
2018-12-05 15:31:01 +01:00
actionOrMoveIndex [ i ] = 0xFF ;
2017-09-08 18:19:20 +02:00
bestMovePointsForTarget [ i ] = - 1 ;
2017-02-02 05:15:38 +01:00
}
else
{
2017-09-08 18:19:20 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
BattleAI_SetupAIData ( gBattleStruct - > field_92 > > 4 ) ;
2017-02-02 05:15:38 +01:00
else
BattleAI_SetupAIData ( 0xF ) ;
2017-10-09 13:41:07 +02:00
2018-02-06 23:09:39 +01:00
gBattlerTarget = i ;
2017-10-09 13:41:07 +02:00
2018-02-06 23:09:39 +01:00
if ( ( i & BIT_SIDE ) ! = ( sBattler_AI & BIT_SIDE ) )
2017-09-05 09:41:48 +02:00
RecordLastUsedMoveByTarget ( ) ;
2017-10-09 13:41:07 +02:00
2017-09-08 18:19:20 +02:00
AI_THINKING_STRUCT - > aiLogicId = 0 ;
AI_THINKING_STRUCT - > movesetIndex = 0 ;
2018-12-22 20:57:12 +01:00
flags = AI_THINKING_STRUCT - > aiFlags ;
while ( flags ! = 0 )
2017-02-02 05:15:38 +01:00
{
2018-12-22 20:57:12 +01:00
if ( flags & 1 )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState = AIState_SettingUp ;
2017-02-02 05:15:38 +01:00
BattleAI_DoAIProcessing ( ) ;
}
2018-12-22 20:57:12 +01:00
flags > > = 1 ;
2017-09-08 18:19:20 +02:00
AI_THINKING_STRUCT - > aiLogicId + + ;
AI_THINKING_STRUCT - > movesetIndex = 0 ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
2017-09-08 18:19:20 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_FLEE )
2018-06-17 16:48:58 +02:00
{
actionOrMoveIndex [ i ] = AI_CHOICE_FLEE ;
}
2017-09-08 18:19:20 +02:00
else if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_WATCH )
2018-06-17 16:48:58 +02:00
{
actionOrMoveIndex [ i ] = AI_CHOICE_WATCH ;
}
2017-02-02 05:15:38 +01:00
else
{
2017-09-08 18:19:20 +02:00
mostViableMovesScores [ 0 ] = AI_THINKING_STRUCT - > score [ 0 ] ;
mostViableMovesIndices [ 0 ] = 0 ;
mostViableMovesNo = 1 ;
2018-12-25 18:50:15 +01:00
for ( j = 1 ; j < MAX_MON_MOVES ; j + + )
2017-02-02 05:15:38 +01:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ j ] ! = 0 )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
if ( mostViableMovesScores [ 0 ] = = AI_THINKING_STRUCT - > score [ j ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostViableMovesScores [ mostViableMovesNo ] = AI_THINKING_STRUCT - > score [ j ] ;
mostViableMovesIndices [ mostViableMovesNo ] = j ;
mostViableMovesNo + + ;
2017-02-02 05:15:38 +01:00
}
2017-09-08 18:19:20 +02:00
if ( mostViableMovesScores [ 0 ] < AI_THINKING_STRUCT - > score [ j ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostViableMovesScores [ 0 ] = AI_THINKING_STRUCT - > score [ j ] ;
mostViableMovesIndices [ 0 ] = j ;
mostViableMovesNo = 1 ;
2017-02-02 05:15:38 +01:00
}
}
}
2017-09-08 18:19:20 +02:00
actionOrMoveIndex [ i ] = mostViableMovesIndices [ Random ( ) % mostViableMovesNo ] ;
bestMovePointsForTarget [ i ] = mostViableMovesScores [ 0 ] ;
2018-06-17 16:48:58 +02:00
// Don't use a move against ally if it has less than 100 points.
2018-02-06 23:09:39 +01:00
if ( i = = ( sBattler_AI ^ BIT_FLANK ) & & bestMovePointsForTarget [ i ] < 100 )
2017-10-09 13:41:07 +02:00
{
2017-09-08 18:19:20 +02:00
bestMovePointsForTarget [ i ] = - 1 ;
2018-06-17 16:48:58 +02:00
mostViableMovesScores [ 0 ] = mostViableMovesScores [ 0 ] ; // Needed to match.
2017-10-09 13:41:07 +02:00
}
2017-02-02 05:15:38 +01:00
}
}
}
2017-09-04 21:43:13 +02:00
2017-09-08 18:19:20 +02:00
mostMovePoints = bestMovePointsForTarget [ 0 ] ;
mostViableTargetsArray [ 0 ] = 0 ;
mostViableTargetsNo = 1 ;
2017-10-09 13:41:07 +02:00
2018-12-25 18:50:15 +01:00
for ( i = 1 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
if ( mostMovePoints = = bestMovePointsForTarget [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostViableTargetsArray [ mostViableTargetsNo ] = i ;
mostViableTargetsNo + + ;
2017-02-02 05:15:38 +01:00
}
2017-09-08 18:19:20 +02:00
if ( mostMovePoints < bestMovePointsForTarget [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostMovePoints = bestMovePointsForTarget [ i ] ;
mostViableTargetsArray [ 0 ] = i ;
mostViableTargetsNo = 1 ;
2017-02-02 05:15:38 +01:00
}
}
2017-10-09 13:41:07 +02:00
2018-02-06 23:09:39 +01:00
gBattlerTarget = mostViableTargetsArray [ Random ( ) % mostViableTargetsNo ] ;
return actionOrMoveIndex [ gBattlerTarget ] ;
2017-02-02 05:15:38 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAI_DoAIProcessing ( void )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
while ( AI_THINKING_STRUCT - > aiState ! = AIState_FinishedProcessing )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
switch ( AI_THINKING_STRUCT - > aiState )
2017-02-02 05:15:38 +01:00
{
2017-10-09 13:41:07 +02:00
case AIState_DoNotProcess : // Needed to match.
2017-02-02 05:15:38 +01:00
break ;
2017-02-04 03:34:56 +01:00
case AIState_SettingUp :
2017-09-05 09:41:48 +02:00
gAIScriptPtr = gBattleAI_ScriptsTable [ AI_THINKING_STRUCT - > aiLogicId ] ; // set AI ptr to logic ID.
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . pp [ AI_THINKING_STRUCT - > movesetIndex ] = = 0 )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > moveConsidered = 0 ;
2017-02-02 05:15:38 +01:00
}
else
{
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > moveConsidered = gBattleMons [ sBattler_AI ] . moves [ AI_THINKING_STRUCT - > movesetIndex ] ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState + + ;
2017-02-02 05:15:38 +01:00
break ;
2017-02-04 03:34:56 +01:00
case AIState_Processing :
if ( AI_THINKING_STRUCT - > moveConsidered ! = 0 )
2018-06-17 16:48:58 +02:00
{
2017-10-09 13:41:07 +02:00
sBattleAICmdTable [ * gAIScriptPtr ] ( ) ; // Run AI command.
2018-06-17 16:48:58 +02:00
}
2017-02-02 05:15:38 +01:00
else
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] = 0 ;
2017-09-05 09:41:48 +02:00
AI_THINKING_STRUCT - > aiAction | = AI_ACTION_DONE ;
2017-02-02 05:15:38 +01:00
}
2017-09-05 09:41:48 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_DONE )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > movesetIndex + + ;
2018-12-25 18:50:15 +01:00
if ( AI_THINKING_STRUCT - > movesetIndex < MAX_MON_MOVES & & ! ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_DO_NOT_ATTACK ) )
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState = AIState_SettingUp ;
2017-02-02 05:15:38 +01:00
else
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState + + ;
2017-09-05 09:41:48 +02:00
AI_THINKING_STRUCT - > aiAction & = ~ ( AI_ACTION_DONE ) ;
2017-02-02 05:15:38 +01:00
}
break ;
}
}
}
2017-09-05 09:41:48 +02:00
static void RecordLastUsedMoveByTarget ( void )
2017-02-02 05:15:38 +01:00
{
s32 i ;
2017-09-04 21:43:13 +02:00
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
if ( BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] = = gLastMoves [ gBattlerTarget ] )
2017-02-02 05:15:38 +01:00
break ;
2018-06-17 16:48:58 +02:00
if ( BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] ! = gLastMoves [ gBattlerTarget ] // HACK: This redundant condition is a hack to make the asm match.
& & BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] = = MOVE_NONE )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] = gLastMoves [ gBattlerTarget ] ;
2017-02-02 05:15:38 +01:00
break ;
}
}
}
2019-02-09 13:21:32 +01:00
static bool32 IsBattlerAIControlled ( u32 battlerId )
2018-07-15 18:07:01 +02:00
{
switch ( GetBattlerPosition ( battlerId ) )
{
case B_POSITION_PLAYER_LEFT :
default :
return FALSE ;
case B_POSITION_OPPONENT_LEFT :
return TRUE ;
case B_POSITION_PLAYER_RIGHT :
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
return FALSE ;
else
return TRUE ;
case B_POSITION_OPPONENT_RIGHT :
return TRUE ;
}
}
2018-02-28 19:37:48 +01:00
void ClearBattlerMoveHistory ( u8 battlerId )
2017-02-02 05:15:38 +01:00
{
s32 i ;
2017-09-04 21:43:13 +02:00
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > usedMoves [ battlerId ] . moves [ i ] = MOVE_NONE ;
2017-02-02 05:15:38 +01:00
}
2018-02-28 19:37:48 +01:00
void RecordAbilityBattle ( u8 battlerId , u8 abilityId )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > abilities [ battlerId ] = abilityId ;
2017-02-02 05:15:38 +01:00
}
2018-02-28 19:37:48 +01:00
void ClearBattlerAbilityHistory ( u8 battlerId )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > abilities [ battlerId ] = ABILITY_NONE ;
2017-02-02 05:15:38 +01:00
}
2018-02-28 19:37:48 +01:00
void RecordItemEffectBattle ( u8 battlerId , u8 itemEffect )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > itemEffects [ battlerId ] = itemEffect ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
void ClearBattlerItemEffectHistory ( u8 battlerId )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > itemEffects [ battlerId ] = 0 ;
2017-02-02 05:15:38 +01:00
}
2018-07-15 18:07:01 +02:00
static void SaveBattlerData ( u8 battlerId )
{
if ( ! IsBattlerAIControlled ( battlerId ) )
{
u32 i ;
AI_THINKING_STRUCT - > saved [ battlerId ] . ability = gBattleMons [ battlerId ] . ability ;
AI_THINKING_STRUCT - > saved [ battlerId ] . heldItem = gBattleMons [ battlerId ] . item ;
AI_THINKING_STRUCT - > saved [ battlerId ] . species = gBattleMons [ battlerId ] . species ;
for ( i = 0 ; i < 4 ; i + + )
AI_THINKING_STRUCT - > saved [ battlerId ] . moves [ i ] = gBattleMons [ battlerId ] . moves [ i ] ;
}
}
static void SetBattlerData ( u8 battlerId )
{
if ( ! IsBattlerAIControlled ( battlerId ) )
{
u32 i ;
// Use the known battler's ability.
if ( BATTLE_HISTORY - > abilities [ battlerId ] ! = ABILITY_NONE )
gBattleMons [ battlerId ] . ability = BATTLE_HISTORY - > abilities [ battlerId ] ;
// Check if mon can only have one ability.
2019-05-17 09:52:20 +02:00
else if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] = = ABILITY_NONE )
gBattleMons [ battlerId ] . ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2018-07-15 18:07:01 +02:00
// The ability is unknown.
2019-05-17 09:52:20 +02:00
else
2018-07-15 18:07:01 +02:00
gBattleMons [ battlerId ] . ability = ABILITY_NONE ;
if ( BATTLE_HISTORY - > itemEffects [ battlerId ] = = 0 )
gBattleMons [ battlerId ] . item = 0 ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( BATTLE_HISTORY - > usedMoves [ battlerId ] . moves [ i ] = = 0 )
gBattleMons [ battlerId ] . moves [ i ] = 0 ;
}
}
}
static void RestoreBattlerData ( u8 battlerId )
{
if ( ! IsBattlerAIControlled ( battlerId ) )
{
u32 i ;
gBattleMons [ battlerId ] . ability = AI_THINKING_STRUCT - > saved [ battlerId ] . ability ;
gBattleMons [ battlerId ] . item = AI_THINKING_STRUCT - > saved [ battlerId ] . heldItem ;
gBattleMons [ battlerId ] . species = AI_THINKING_STRUCT - > saved [ battlerId ] . species ;
for ( i = 0 ; i < 4 ; i + + )
gBattleMons [ battlerId ] . moves [ i ] = AI_THINKING_STRUCT - > saved [ battlerId ] . moves [ i ] ;
}
}
2018-07-23 21:36:05 +02:00
static bool32 AI_GetIfCrit ( u32 move , u8 battlerAtk , u8 battlerDef )
{
bool32 isCrit ;
switch ( CalcCritChanceStage ( battlerAtk , battlerDef , move , FALSE ) )
{
case - 1 :
case 0 :
default :
isCrit = FALSE ;
break ;
case 1 :
if ( gBattleMoves [ move ] . flags & FLAG_HIGH_CRIT & & ( Random ( ) % 5 = = 0 ) )
isCrit = TRUE ;
else
isCrit = FALSE ;
break ;
case 2 :
if ( gBattleMoves [ move ] . flags & FLAG_HIGH_CRIT & & ( Random ( ) % 2 = = 0 ) )
isCrit = TRUE ;
else if ( ! ( gBattleMoves [ move ] . flags & FLAG_HIGH_CRIT ) & & ( Random ( ) % 4 ) = = 0 )
isCrit = TRUE ;
else
isCrit = FALSE ;
break ;
2018-07-23 22:18:56 +02:00
case - 2 :
2018-07-23 21:36:05 +02:00
case 3 :
case 4 :
isCrit = TRUE ;
break ;
}
return isCrit ;
}
2018-07-15 12:39:07 +02:00
s32 AI_CalcDamage ( u16 move , u8 battlerAtk , u8 battlerDef )
{
2018-07-29 11:32:40 +02:00
s32 dmg , moveType ;
2018-07-15 18:07:01 +02:00
SaveBattlerData ( battlerAtk ) ;
SaveBattlerData ( battlerDef ) ;
SetBattlerData ( battlerAtk ) ;
SetBattlerData ( battlerDef ) ;
2018-07-29 11:32:40 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
SetTypeBeforeUsingMove ( move , battlerAtk ) ;
GET_MOVE_TYPE ( move , moveType ) ;
2019-04-02 00:14:01 +02:00
dmg = CalculateMoveDamage ( move , battlerAtk , battlerDef , moveType , 0 , AI_GetIfCrit ( move , battlerAtk , battlerDef ) , FALSE , FALSE ) ;
2018-07-15 18:07:01 +02:00
RestoreBattlerData ( battlerAtk ) ;
RestoreBattlerData ( battlerDef ) ;
return dmg ;
2018-07-15 12:39:07 +02:00
}
s32 AI_CalcPartyMonDamage ( u16 move , u8 battlerAtk , u8 battlerDef , struct Pokemon * mon )
{
2018-07-15 18:07:01 +02:00
s32 dmg ;
u32 i ;
struct BattlePokemon * battleMons = Alloc ( sizeof ( struct BattlePokemon ) * MAX_BATTLERS_COUNT ) ;
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
battleMons [ i ] = gBattleMons [ i ] ;
PokemonToBattleMon ( mon , & gBattleMons [ battlerAtk ] ) ;
dmg = AI_CalcDamage ( move , battlerAtk , battlerDef ) ;
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
gBattleMons [ i ] = battleMons [ i ] ;
Free ( battleMons ) ;
return dmg ;
2018-07-15 12:39:07 +02:00
}
u16 AI_GetTypeEffectiveness ( u16 move , u8 battlerAtk , u8 battlerDef )
{
2018-07-15 18:07:01 +02:00
u16 typeEffectiveness ;
SaveBattlerData ( battlerAtk ) ;
SaveBattlerData ( battlerDef ) ;
SetBattlerData ( battlerAtk ) ;
SetBattlerData ( battlerDef ) ;
typeEffectiveness = CalcTypeEffectivenessMultiplier ( move , gBattleMoves [ move ] . type , battlerAtk , battlerDef , FALSE ) ;
RestoreBattlerData ( battlerAtk ) ;
RestoreBattlerData ( battlerDef ) ;
return typeEffectiveness ;
2018-07-15 12:39:07 +02:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_random_less_than ( void )
2017-02-02 05:15:38 +01:00
{
u16 random = Random ( ) ;
2017-02-04 03:34:56 +01:00
if ( random % 256 < gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_random_greater_than ( void )
2017-02-04 03:34:56 +01:00
{
u16 random = Random ( ) ;
if ( random % 256 > gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_random_equal ( void )
2017-02-04 03:34:56 +01:00
{
u16 random = Random ( ) ;
if ( random % 256 = = gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_random_not_equal ( void )
2017-02-04 03:34:56 +01:00
{
u16 random = Random ( ) ;
if ( random % 256 ! = gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_score ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] + = gAIScriptPtr [ 1 ] ; // Add the result to the array of the move consider's score.
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] < 0 ) // If the score is negative, flatten it to 0.
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] = 0 ;
gAIScriptPtr + = 2 ; // AI return.
}
2019-05-23 11:41:35 +02:00
static u8 BattleAI_GetWantedBattler ( u8 wantedBattler )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
switch ( wantedBattler )
{
case AI_USER :
return sBattler_AI ;
case AI_TARGET :
default :
return gBattlerTarget ;
case AI_USER_PARTNER :
return sBattler_AI ^ BIT_FLANK ;
case AI_TARGET_PARTNER :
return gBattlerTarget ^ BIT_FLANK ;
}
}
2017-02-04 03:34:56 +01:00
2019-05-23 11:41:35 +02:00
static void BattleAICmd_if_hp_less_than ( void )
{
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( ( u32 ) ( 100 * gBattleMons [ battlerId ] . hp / gBattleMons [ battlerId ] . maxHP ) < gAIScriptPtr [ 2 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 7 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_hp_more_than ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( ( u32 ) ( 100 * gBattleMons [ battlerId ] . hp / gBattleMons [ battlerId ] . maxHP ) > gAIScriptPtr [ 2 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 7 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_hp_equal ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( ( u32 ) ( 100 * gBattleMons [ battlerId ] . hp / gBattleMons [ battlerId ] . maxHP ) = = gAIScriptPtr [ 2 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 7 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_hp_not_equal ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( ( u32 ) ( 100 * gBattleMons [ battlerId ] . hp / gBattleMons [ battlerId ] . maxHP ) ! = gAIScriptPtr [ 2 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 7 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_status ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2018-07-16 20:47:30 +02:00
if ( gBattleMons [ battlerId ] . status1 & status )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_status ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( ! ( gBattleMons [ battlerId ] . status1 & status ) )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_status2 ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( ( gBattleMons [ battlerId ] . status2 & status ) )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_status2 ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( ! ( gBattleMons [ battlerId ] . status2 & status ) )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_status3 ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2018-07-16 20:47:30 +02:00
if ( gStatuses3 [ battlerId ] & status )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_status3 ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( ! ( gStatuses3 [ battlerId ] & status ) )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_side_affecting ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
u32 side = GET_BATTLER_SIDE ( battlerId ) ;
2017-02-04 03:34:56 +01:00
2018-07-16 20:47:30 +02:00
if ( gSideStatuses [ side ] & status )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_side_affecting ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-23 11:41:35 +02:00
u16 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u32 status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
u32 side = GET_BATTLER_SIDE ( battlerId ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( ! ( gSideStatuses [ side ] & status ) )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_less_than ( void )
2017-02-04 03:34:56 +01:00
{
if ( AI_THINKING_STRUCT - > funcResult < gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_more_than ( void )
2017-02-04 03:34:56 +01:00
{
if ( AI_THINKING_STRUCT - > funcResult > gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_equal ( void )
2017-02-04 03:34:56 +01:00
{
if ( AI_THINKING_STRUCT - > funcResult = = gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_equal ( void )
2017-02-04 03:34:56 +01:00
{
if ( AI_THINKING_STRUCT - > funcResult ! = gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-02 05:15:38 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_less_than_ptr ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u8 * value = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
if ( AI_THINKING_STRUCT - > funcResult < * value )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 9 ;
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_more_than_ptr ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u8 * value = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
if ( AI_THINKING_STRUCT - > funcResult > * value )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 9 ;
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_equal_ptr ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u8 * value = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
if ( AI_THINKING_STRUCT - > funcResult = = * value )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 9 ;
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_not_equal_ptr ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u8 * value = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
if ( AI_THINKING_STRUCT - > funcResult ! = * value )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 9 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_move ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
u16 move = T1_READ_16 ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
if ( AI_THINKING_STRUCT - > moveConsidered = = move )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 7 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_move ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
u16 move = T1_READ_16 ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
if ( AI_THINKING_STRUCT - > moveConsidered ! = move )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 7 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_in_bytes ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u8 * ptr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
while ( * ptr ! = 0xFF )
{
if ( AI_THINKING_STRUCT - > funcResult = = * ptr )
{
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
return ;
}
ptr + + ;
}
gAIScriptPtr + = 9 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_in_bytes ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u8 * ptr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
while ( * ptr ! = 0xFF )
{
if ( AI_THINKING_STRUCT - > funcResult = = * ptr )
{
gAIScriptPtr + = 9 ;
return ;
}
ptr + + ;
}
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
}
2017-10-09 13:41:07 +02:00
static void BattleAICmd_if_in_hwords ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
const u16 * ptr = ( const u16 * ) T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
while ( * ptr ! = 0xFFFF )
{
if ( AI_THINKING_STRUCT - > funcResult = = * ptr )
{
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
return ;
}
ptr + + ;
}
gAIScriptPtr + = 9 ;
}
2017-10-09 13:41:07 +02:00
static void BattleAICmd_if_not_in_hwords ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
const u16 * ptr = ( const u16 * ) T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
while ( * ptr ! = 0xFFFF )
{
if ( AI_THINKING_STRUCT - > funcResult = = * ptr )
{
gAIScriptPtr + = 9 ;
return ;
}
ptr + + ;
}
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_user_has_attacking_move ( void )
2017-02-04 03:34:56 +01:00
{
s32 i ;
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ i ] ! = 0
& & gBattleMoves [ gBattleMons [ sBattler_AI ] . moves [ i ] ] . power ! = 0 )
2017-02-04 03:34:56 +01:00
break ;
}
2018-06-17 16:48:58 +02:00
2018-12-25 18:50:15 +01:00
if ( i = = MAX_MON_MOVES )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 5 ;
else
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_user_has_no_attacking_moves ( void )
2017-02-04 03:34:56 +01:00
{
s32 i ;
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ i ] ! = 0
& & gBattleMoves [ gBattleMons [ sBattler_AI ] . moves [ i ] ] . power ! = 0 )
2017-02-04 03:34:56 +01:00
break ;
}
2018-06-17 16:48:58 +02:00
2018-12-25 18:50:15 +01:00
if ( i ! = MAX_MON_MOVES )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 5 ;
else
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_turn_count ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-05 09:41:48 +02:00
AI_THINKING_STRUCT - > funcResult = gBattleResults . battleTurnCounter ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_type ( void )
2017-02-04 03:34:56 +01:00
{
u8 typeVar = gAIScriptPtr [ 1 ] ;
switch ( typeVar )
{
2017-12-30 16:04:31 +01:00
case AI_TYPE1_USER : // AI user primary type
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ sBattler_AI ] . type1 ;
2017-02-04 03:34:56 +01:00
break ;
2017-12-30 16:04:31 +01:00
case AI_TYPE1_TARGET : // target primary type
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ gBattlerTarget ] . type1 ;
2017-02-04 03:34:56 +01:00
break ;
2017-12-30 16:04:31 +01:00
case AI_TYPE2_USER : // AI user secondary type
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ sBattler_AI ] . type2 ;
2017-02-04 03:34:56 +01:00
break ;
2017-12-30 16:04:31 +01:00
case AI_TYPE2_TARGET : // target secondary type
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ gBattlerTarget ] . type2 ;
2017-02-04 03:34:56 +01:00
break ;
2017-12-30 16:04:31 +01:00
case AI_TYPE_MOVE : // type of move being pointed to
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . type ;
break ;
}
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_is_of_type ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-09-04 21:43:13 +02:00
2018-06-17 16:48:58 +02:00
if ( IS_BATTLER_OF_TYPE ( battlerId , gAIScriptPtr [ 2 ] ) )
2017-12-30 12:19:02 +01:00
AI_THINKING_STRUCT - > funcResult = TRUE ;
2017-02-04 03:34:56 +01:00
else
2017-12-30 12:19:02 +01:00
AI_THINKING_STRUCT - > funcResult = FALSE ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 3 ;
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_get_considered_move_power ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power ;
gAIScriptPtr + = 1 ;
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_get_how_powerful_move_is ( void )
2017-02-04 03:34:56 +01:00
{
2017-10-09 13:41:07 +02:00
s32 i , checkedMove ;
s32 moveDmgs [ 4 ] ;
for ( i = 0 ; sDiscouragedPowerfulMoveEffects [ i ] ! = 0xFFFF ; i + + )
{
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect = = sDiscouragedPowerfulMoveEffects [ i ] )
break ;
}
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power > 1
& & sDiscouragedPowerfulMoveEffects [ i ] = = 0xFFFF )
{
* ( & gBattleStruct - > dynamicMoveType ) = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-10-09 13:41:07 +02:00
2018-12-25 18:50:15 +01:00
for ( checkedMove = 0 ; checkedMove < MAX_MON_MOVES ; checkedMove + + )
2017-10-09 13:41:07 +02:00
{
for ( i = 0 ; sDiscouragedPowerfulMoveEffects [ i ] ! = 0xFFFF ; i + + )
{
2018-02-06 23:09:39 +01:00
if ( gBattleMoves [ gBattleMons [ sBattler_AI ] . moves [ checkedMove ] ] . effect = = sDiscouragedPowerfulMoveEffects [ i ] )
2017-10-09 13:41:07 +02:00
break ;
}
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ checkedMove ] ! = MOVE_NONE
2017-10-09 13:41:07 +02:00
& & sDiscouragedPowerfulMoveEffects [ i ] = = 0xFFFF
2018-02-06 23:09:39 +01:00
& & gBattleMoves [ gBattleMons [ sBattler_AI ] . moves [ checkedMove ] ] . power > 1 )
2017-10-09 13:41:07 +02:00
{
2018-02-06 23:09:39 +01:00
gCurrentMove = gBattleMons [ sBattler_AI ] . moves [ checkedMove ] ;
2018-07-15 12:39:07 +02:00
moveDmgs [ checkedMove ] = AI_CalcDamage ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
moveDmgs [ checkedMove ] = moveDmgs [ checkedMove ] * AI_THINKING_STRUCT - > simulatedRNG [ checkedMove ] / 100 ;
2017-10-09 13:41:07 +02:00
if ( moveDmgs [ checkedMove ] = = 0 )
moveDmgs [ checkedMove ] = 1 ;
}
else
{
moveDmgs [ checkedMove ] = 0 ;
}
}
2018-12-25 18:50:15 +01:00
for ( checkedMove = 0 ; checkedMove < MAX_MON_MOVES ; checkedMove + + )
2017-10-09 13:41:07 +02:00
{
if ( moveDmgs [ checkedMove ] > moveDmgs [ AI_THINKING_STRUCT - > movesetIndex ] )
break ;
}
2018-12-25 18:50:15 +01:00
if ( checkedMove = = MAX_MON_MOVES )
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = MOVE_MOST_POWERFUL ; // Is the most powerful.
2017-10-09 13:41:07 +02:00
else
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = MOVE_NOT_MOST_POWERFUL ; // Not the most powerful.
2017-10-09 13:41:07 +02:00
}
else
{
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = MOVE_POWER_DISCOURAGED ; // Highly discouraged in terms of power.
2017-10-09 13:41:07 +02:00
}
gAIScriptPtr + + ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
static void BattleAICmd_get_last_used_battler_move ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gLastMoves [ sBattler_AI ] ;
2017-02-04 03:34:56 +01:00
else
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gLastMoves [ gBattlerTarget ] ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2019-05-20 10:10:00 +02:00
static void BattleAICmd_if_equal_u32 ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-20 10:10:00 +02:00
if ( T1_READ_32 ( & gAIScriptPtr [ 1 ] ) = = AI_THINKING_STRUCT - > funcResult )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
else
2019-05-20 10:10:00 +02:00
gAIScriptPtr + = 9 ;
2017-02-04 03:34:56 +01:00
}
2019-05-20 10:10:00 +02:00
static void BattleAICmd_if_not_equal_u32 ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-20 10:10:00 +02:00
if ( T1_READ_32 ( & gAIScriptPtr [ 1 ] ) ! = AI_THINKING_STRUCT - > funcResult )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2017-02-04 03:34:56 +01:00
else
2019-05-20 10:10:00 +02:00
gAIScriptPtr + = 9 ;
2017-02-04 03:34:56 +01:00
}
2019-02-16 18:23:56 +01:00
static void BattleAICmd_if_user_goes ( void )
2017-02-04 03:34:56 +01:00
{
2019-02-16 14:54:17 +01:00
u32 fasterAI = 0 , fasterPlayer = 0 , i ;
s8 prioAI , prioPlayer ;
// Check move priorities first.
prioAI = GetMovePriority ( sBattler_AI , AI_THINKING_STRUCT - > moveConsidered ) ;
SaveBattlerData ( gBattlerTarget ) ;
SetBattlerData ( gBattlerTarget ) ;
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
{
if ( gBattleMons [ gBattlerTarget ] . moves [ i ] = = 0 | | gBattleMons [ gBattlerTarget ] . moves [ i ] = = 0xFFFF )
continue ;
prioPlayer = GetMovePriority ( gBattlerTarget , gBattleMons [ gBattlerTarget ] . moves [ i ] ) ;
if ( prioAI > prioPlayer )
fasterAI + + ;
else if ( prioPlayer > prioAI )
fasterPlayer + + ;
}
RestoreBattlerData ( gBattlerTarget ) ;
if ( fasterAI > fasterPlayer )
{
if ( gAIScriptPtr [ 1 ] = = 0 )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
else
gAIScriptPtr + = 6 ;
}
else if ( fasterAI < fasterPlayer )
{
if ( gAIScriptPtr [ 1 ] = = 1 )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
else
gAIScriptPtr + = 6 ;
}
2017-02-04 03:34:56 +01:00
else
2019-02-16 14:54:17 +01:00
{
// Priorities are the same(at least comparing to moves the AI is aware of), decide by speed.
if ( GetWhoStrikesFirst ( sBattler_AI , gBattlerTarget , TRUE ) = = gAIScriptPtr [ 1 ] )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
else
gAIScriptPtr + = 6 ;
}
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_2A ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_2B ( void )
2017-02-04 03:34:56 +01:00
{
}
2019-06-11 10:45:12 +02:00
static s32 CountUsablePartyMons ( u8 battlerId )
2017-02-04 03:34:56 +01:00
{
2019-06-11 10:45:12 +02:00
s32 battlerOnField1 , battlerOnField2 , i , ret ;
2017-02-04 03:34:56 +01:00
struct Pokemon * party ;
2018-02-28 19:37:48 +01:00
if ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
2017-02-04 03:34:56 +01:00
party = gPlayerParty ;
else
party = gEnemyParty ;
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
2018-06-17 16:48:58 +02:00
battlerOnField1 = gBattlerPartyIndexes [ battlerId ] ;
2019-06-11 10:45:12 +02:00
battlerOnField2 = gBattlerPartyIndexes [ GetBattlerAtPosition ( GetBattlerPosition ( battlerId ) ^ BIT_FLANK ) ] ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
else // In singles there's only one battlerId by side.
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
battlerOnField1 = gBattlerPartyIndexes [ battlerId ] ;
battlerOnField2 = gBattlerPartyIndexes [ battlerId ] ;
2017-02-04 03:34:56 +01:00
}
2019-06-11 10:45:12 +02:00
ret = 0 ;
2017-12-30 12:19:02 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
if ( i ! = battlerOnField1 & & i ! = battlerOnField2
2017-02-04 03:34:56 +01:00
& & GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_NONE
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
{
2019-06-11 10:45:12 +02:00
ret + + ;
2017-02-04 03:34:56 +01:00
}
}
2019-06-11 10:45:12 +02:00
return ret ;
}
static void BattleAICmd_count_usable_party_mons ( void )
{
AI_THINKING_STRUCT - > funcResult = CountUsablePartyMons ( BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ) ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_considered_move ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = AI_THINKING_STRUCT - > moveConsidered ;
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_considered_move_effect ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect ;
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_ability ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-20 12:03:00 +02:00
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2019-05-20 12:03:00 +02:00
if ( ! IsBattlerAIControlled ( battlerId ) )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
if ( BATTLE_HISTORY - > abilities [ battlerId ] ! = 0 )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = BATTLE_HISTORY - > abilities [ battlerId ] ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
return ;
}
2017-09-04 21:43:13 +02:00
2017-02-04 03:34:56 +01:00
// abilities that prevent fleeing.
2018-02-28 19:37:48 +01:00
if ( gBattleMons [ battlerId ] . ability = = ABILITY_SHADOW_TAG
| | gBattleMons [ battlerId ] . ability = = ABILITY_MAGNET_PULL
| | gBattleMons [ battlerId ] . ability = = ABILITY_ARENA_TRAP )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ battlerId ] . ability ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
return ;
}
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
// AI has no knowledge of opponent, so it guesses which ability.
2017-09-05 09:41:48 +02:00
if ( Random ( ) & 1 )
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2017-02-04 03:34:56 +01:00
else
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ;
2017-09-04 21:43:13 +02:00
}
2017-02-04 03:34:56 +01:00
else
{
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ; // It's definitely ability 1.
2017-02-04 03:34:56 +01:00
}
}
else
{
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ; // AI can't actually reach this part since no pokemon has ability 2 and no ability 1.
2017-02-04 03:34:56 +01:00
}
}
else
{
// The AI knows its own ability.
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ battlerId ] . ability ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_check_ability ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u32 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-10-09 13:41:07 +02:00
u32 ability = gAIScriptPtr [ 2 ] ;
2017-09-04 21:43:13 +02:00
2019-05-20 12:03:00 +02:00
if ( ! IsBattlerAIControlled ( battlerId ) )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
if ( BATTLE_HISTORY - > abilities [ battlerId ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
ability = BATTLE_HISTORY - > abilities [ battlerId ] ;
2017-09-05 09:41:48 +02:00
AI_THINKING_STRUCT - > funcResult = ability ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
// Abilities that prevent fleeing.
2018-02-28 19:37:48 +01:00
else if ( gBattleMons [ battlerId ] . ability = = ABILITY_SHADOW_TAG
| | gBattleMons [ battlerId ] . ability = = ABILITY_MAGNET_PULL
| | gBattleMons [ battlerId ] . ability = = ABILITY_ARENA_TRAP )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
ability = gBattleMons [ battlerId ] . ability ;
2017-09-05 09:41:48 +02:00
}
2019-05-14 15:42:55 +02:00
else if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ! = ABILITY_NONE )
2017-09-05 09:41:48 +02:00
{
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u8 abilityDummyVariable = ability ; // Needed to match.
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ! = abilityDummyVariable
& & gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ! = abilityDummyVariable )
2017-02-04 03:34:56 +01:00
{
2019-05-14 15:42:55 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2017-02-04 03:34:56 +01:00
}
else
2018-06-17 16:48:58 +02:00
{
ability = ABILITY_NONE ;
}
2017-09-05 09:41:48 +02:00
}
else
{
2019-05-14 15:42:55 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2017-02-04 03:34:56 +01:00
}
}
2017-09-05 09:41:48 +02:00
else
{
2019-05-14 15:42:55 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ; // AI can't actually reach this part since no pokemon has ability 2 and no ability 1.
2017-09-05 09:41:48 +02:00
}
2017-02-04 03:34:56 +01:00
}
else
{
2017-09-05 09:41:48 +02:00
// The AI knows its own or partner's ability.
2018-02-28 19:37:48 +01:00
ability = gBattleMons [ battlerId ] . ability ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
2017-09-05 09:41:48 +02:00
if ( ability = = 0 )
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = 2 ; // Unable to answer.
2017-09-05 09:41:48 +02:00
else if ( ability = = gAIScriptPtr [ 2 ] )
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = 1 ; // Pokemon has the ability we wanted to check.
2017-02-04 03:34:56 +01:00
else
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = 0 ; // Pokemon doesn't have the ability we wanted to check.
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 3 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_highest_type_effectiveness ( void )
2017-02-04 03:34:56 +01:00
{
s32 i ;
2018-06-17 16:48:58 +02:00
u8 * dynamicMoveType ;
2017-02-04 03:34:56 +01:00
2018-07-15 12:39:07 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > funcResult = 0 ;
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
gCurrentMove = gBattleMons [ sBattler_AI ] . moves [ i ] ;
2018-06-17 16:48:58 +02:00
if ( gCurrentMove ! = MOVE_NONE )
2017-02-04 03:34:56 +01:00
{
2018-07-15 12:39:07 +02:00
u32 effectivenessMultiplier = AI_GetTypeEffectiveness ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
2017-02-04 03:34:56 +01:00
2018-07-15 12:39:07 +02:00
switch ( effectivenessMultiplier )
{
case UQ_4_12 ( 0.0 ) :
default :
gBattleMoveDamage = AI_EFFECTIVENESS_x0 ;
break ;
case UQ_4_12 ( 0.25 ) :
gBattleMoveDamage = AI_EFFECTIVENESS_x0_25 ;
break ;
case UQ_4_12 ( 0.5 ) :
gBattleMoveDamage = AI_EFFECTIVENESS_x0_5 ;
break ;
case UQ_4_12 ( 1.0 ) :
gBattleMoveDamage = AI_EFFECTIVENESS_x1 ;
break ;
case UQ_4_12 ( 2.0 ) :
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x2 ;
2018-07-15 12:39:07 +02:00
break ;
case UQ_4_12 ( 4.0 ) :
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x4 ;
2018-07-15 12:39:07 +02:00
break ;
}
2017-02-04 03:34:56 +01:00
if ( AI_THINKING_STRUCT - > funcResult < gBattleMoveDamage )
AI_THINKING_STRUCT - > funcResult = gBattleMoveDamage ;
}
}
2018-06-17 16:48:58 +02:00
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_type_effectiveness ( void )
2017-02-04 03:34:56 +01:00
{
u8 damageVar ;
2018-07-15 12:39:07 +02:00
u32 effectivenessMultiplier ;
2017-02-04 03:34:56 +01:00
2017-09-05 09:41:48 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-08-31 16:48:24 +02:00
gCurrentMove = AI_THINKING_STRUCT - > moveConsidered ;
2017-02-04 03:34:56 +01:00
2018-07-15 12:39:07 +02:00
effectivenessMultiplier = AI_GetTypeEffectiveness ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
switch ( effectivenessMultiplier )
{
case UQ_4_12 ( 0.0 ) :
default :
damageVar = AI_EFFECTIVENESS_x0 ;
break ;
case UQ_4_12 ( 0.25 ) :
damageVar = AI_EFFECTIVENESS_x0_25 ;
break ;
case UQ_4_12 ( 0.5 ) :
damageVar = AI_EFFECTIVENESS_x0_5 ;
break ;
case UQ_4_12 ( 1.0 ) :
damageVar = AI_EFFECTIVENESS_x1 ;
break ;
case UQ_4_12 ( 2.0 ) :
damageVar = AI_EFFECTIVENESS_x2 ;
break ;
case UQ_4_12 ( 4.0 ) :
damageVar = AI_EFFECTIVENESS_x4 ;
break ;
}
2017-02-04 03:34:56 +01:00
if ( damageVar = = gAIScriptPtr [ 1 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_32 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_33 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_status_in_party ( void )
2017-02-04 03:34:56 +01:00
{
struct Pokemon * party ;
2018-06-17 16:48:58 +02:00
s32 i ;
2017-02-04 03:34:56 +01:00
u32 statusToCompareTo ;
2019-05-23 11:41:35 +02:00
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
party = ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER ) ? gPlayerParty : gEnemyParty ;
2017-02-04 03:34:56 +01:00
2018-03-01 00:59:52 +01:00
statusToCompareTo = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-02-04 03:34:56 +01:00
{
u16 species = GetMonData ( & party [ i ] , MON_DATA_SPECIES ) ;
u16 hp = GetMonData ( & party [ i ] , MON_DATA_HP ) ;
u32 status = GetMonData ( & party [ i ] , MON_DATA_STATUS ) ;
if ( species ! = SPECIES_NONE & & species ! = SPECIES_EGG & & hp ! = 0 & & status = = statusToCompareTo )
{
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
return ;
}
}
gAIScriptPtr + = 10 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_status_not_in_party ( void )
2017-02-04 03:34:56 +01:00
{
struct Pokemon * party ;
2018-06-17 16:48:58 +02:00
s32 i ;
2017-02-04 03:34:56 +01:00
u32 statusToCompareTo ;
2019-05-23 11:41:35 +02:00
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
party = ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER ) ? gPlayerParty : gEnemyParty ;
2017-02-04 03:34:56 +01:00
2018-03-01 00:59:52 +01:00
statusToCompareTo = T1_READ_32 ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
2017-12-30 12:19:02 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-02-04 03:34:56 +01:00
{
u16 species = GetMonData ( & party [ i ] , MON_DATA_SPECIES ) ;
u16 hp = GetMonData ( & party [ i ] , MON_DATA_HP ) ;
u32 status = GetMonData ( & party [ i ] , MON_DATA_STATUS ) ;
if ( species ! = SPECIES_NONE & & species ! = SPECIES_EGG & & hp ! = 0 & & status = = statusToCompareTo )
{
2018-07-15 12:39:07 +02:00
gAIScriptPtr + = 10 ;
return ;
2017-02-04 03:34:56 +01:00
}
}
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_weather ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-05 09:41:48 +02:00
if ( gBattleWeather & WEATHER_RAIN_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_RAIN ;
2019-05-20 12:03:00 +02:00
else if ( gBattleWeather & WEATHER_SANDSTORM_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_SANDSTORM ;
2019-05-20 12:03:00 +02:00
else if ( gBattleWeather & WEATHER_SUN_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_SUN ;
2019-05-20 12:03:00 +02:00
else if ( gBattleWeather & WEATHER_HAIL_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_HAIL ;
2019-05-20 12:03:00 +02:00
else
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_NONE ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_effect ( void )
2017-02-04 03:34:56 +01:00
{
2018-09-02 15:50:18 +02:00
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect = = T1_READ_16 ( gAIScriptPtr + 1 ) )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
2018-09-02 15:50:18 +02:00
gAIScriptPtr + = 7 ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_not_effect ( void )
2017-02-04 03:34:56 +01:00
{
2018-09-02 15:50:18 +02:00
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect ! = T1_READ_16 ( gAIScriptPtr + 1 ) )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
else
2018-09-02 15:50:18 +02:00
gAIScriptPtr + = 7 ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_stat_level_less_than ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u32 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( gBattleMons [ battlerId ] . statStages [ gAIScriptPtr [ 2 ] ] < gAIScriptPtr [ 3 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 8 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_stat_level_more_than ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u32 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( gBattleMons [ battlerId ] . statStages [ gAIScriptPtr [ 2 ] ] > gAIScriptPtr [ 3 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 8 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_stat_level_equal ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u32 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( gBattleMons [ battlerId ] . statStages [ gAIScriptPtr [ 2 ] ] = = gAIScriptPtr [ 3 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 8 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_stat_level_not_equal ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u32 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
if ( gBattleMons [ battlerId ] . statStages [ gAIScriptPtr [ 2 ] ] ! = gAIScriptPtr [ 3 ] )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 8 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_can_faint ( void )
2017-02-04 03:34:56 +01:00
{
2018-07-15 12:39:07 +02:00
s32 dmg ;
2019-05-23 11:41:35 +02:00
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power = = 0 )
2017-02-04 03:34:56 +01:00
{
gAIScriptPtr + = 5 ;
return ;
}
2017-09-05 09:41:48 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2018-07-15 12:39:07 +02:00
dmg = AI_CalcDamage ( AI_THINKING_STRUCT - > moveConsidered , sBattler_AI , gBattlerTarget ) ;
dmg = dmg * AI_THINKING_STRUCT - > simulatedRNG [ AI_THINKING_STRUCT - > movesetIndex ] / 100 ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Moves always do at least 1 damage.
2018-07-15 12:39:07 +02:00
if ( dmg = = 0 )
dmg = 1 ;
2017-02-04 03:34:56 +01:00
2018-07-15 12:39:07 +02:00
if ( gBattleMons [ gBattlerTarget ] . hp < = dmg )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 5 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_cant_faint ( void )
2017-02-04 03:34:56 +01:00
{
2018-07-15 12:39:07 +02:00
s32 dmg ;
2017-02-04 03:34:56 +01:00
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power < 2 )
{
gAIScriptPtr + = 5 ;
return ;
}
2017-09-05 09:41:48 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2018-07-15 12:39:07 +02:00
dmg = AI_CalcDamage ( AI_THINKING_STRUCT - > moveConsidered , sBattler_AI , gBattlerTarget ) ;
dmg = dmg * AI_THINKING_STRUCT - > simulatedRNG [ AI_THINKING_STRUCT - > movesetIndex ] / 100 ;
2017-02-04 03:34:56 +01:00
2018-07-15 12:39:07 +02:00
// Moves always do at least 1 damage.
if ( dmg = = 0 )
dmg = 1 ;
2017-02-04 03:34:56 +01:00
2018-07-15 12:39:07 +02:00
if ( gBattleMons [ gBattlerTarget ] . hp > dmg )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 5 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_has_move ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
s32 i ;
2017-12-30 12:19:02 +01:00
const u16 * movePtr = ( u16 * ) ( gAIScriptPtr + 2 ) ;
2017-09-04 21:43:13 +02:00
2017-12-30 12:19:02 +01:00
switch ( gAIScriptPtr [ 1 ] )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
case AI_USER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2018-06-17 16:48:58 +02:00
{
if ( gBattleMons [ sBattler_AI ] . moves [ i ] = = * movePtr )
break ;
}
2018-12-25 18:50:15 +01:00
if ( i = = MAX_MON_MOVES )
2018-06-17 16:48:58 +02:00
gAIScriptPtr + = 8 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
break ;
case AI_USER_PARTNER :
if ( gBattleMons [ sBattler_AI ^ BIT_FLANK ] . hp = = 0 )
{
gAIScriptPtr + = 8 ;
break ;
}
else
{
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
if ( gBattleMons [ sBattler_AI ^ BIT_FLANK ] . moves [ i ] = = * movePtr )
2017-02-04 03:34:56 +01:00
break ;
}
2018-06-17 16:48:58 +02:00
}
2018-12-25 18:50:15 +01:00
if ( i = = MAX_MON_MOVES )
2018-06-17 16:48:58 +02:00
gAIScriptPtr + = 8 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
break ;
case AI_TARGET :
case AI_TARGET_PARTNER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2018-06-17 16:48:58 +02:00
{
if ( BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] = = * movePtr )
break ;
}
2018-12-25 18:50:15 +01:00
if ( i = = MAX_MON_MOVES )
2018-06-17 16:48:58 +02:00
gAIScriptPtr + = 8 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
break ;
2017-02-04 03:34:56 +01:00
}
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_doesnt_have_move ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
s32 i ;
2017-12-30 12:19:02 +01:00
const u16 * movePtr = ( u16 * ) ( gAIScriptPtr + 2 ) ;
2017-09-04 21:43:13 +02:00
2017-02-04 03:34:56 +01:00
switch ( gAIScriptPtr [ 1 ] )
{
2018-06-17 16:48:58 +02:00
case AI_USER :
case AI_USER_PARTNER : // UB: no separate check for user partner.
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2018-06-17 16:48:58 +02:00
{
if ( gBattleMons [ sBattler_AI ] . moves [ i ] = = * movePtr )
break ;
}
2018-12-25 18:50:15 +01:00
if ( i ! = MAX_MON_MOVES )
2018-06-17 16:48:58 +02:00
gAIScriptPtr + = 8 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
break ;
case AI_TARGET :
case AI_TARGET_PARTNER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2018-06-17 16:48:58 +02:00
{
if ( BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] = = * movePtr )
break ;
}
2018-12-25 18:50:15 +01:00
if ( i ! = MAX_MON_MOVES )
2018-06-17 16:48:58 +02:00
gAIScriptPtr + = 8 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
break ;
2017-02-04 03:34:56 +01:00
}
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_has_move_with_effect ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
s32 i ;
2017-02-04 03:34:56 +01:00
switch ( gAIScriptPtr [ 1 ] )
{
2017-09-05 13:01:24 +02:00
case AI_USER :
case AI_USER_PARTNER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ i ] ! = 0 & & gBattleMoves [ gBattleMons [ sBattler_AI ] . moves [ i ] ] . effect = = gAIScriptPtr [ 2 ] )
2017-02-04 03:34:56 +01:00
break ;
}
2018-12-25 18:50:15 +01:00
if ( i = = MAX_MON_MOVES )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 7 ;
else
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
break ;
2017-09-05 13:01:24 +02:00
case AI_TARGET :
case AI_TARGET_PARTNER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-09-02 15:50:18 +02:00
if ( gBattleMons [ gBattlerTarget ] . moves [ i ] ! = 0 & & gBattleMoves [ BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] ] . effect = = gAIScriptPtr [ 2 ] )
2017-02-04 03:34:56 +01:00
break ;
}
2018-12-25 18:50:15 +01:00
if ( i = = MAX_MON_MOVES )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 7 ;
else
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
break ;
}
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_doesnt_have_move_with_effect ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
s32 i ;
2017-02-04 03:34:56 +01:00
switch ( gAIScriptPtr [ 1 ] )
{
2017-09-05 13:01:24 +02:00
case AI_USER :
case AI_USER_PARTNER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ i ] ! = 0 & & gBattleMoves [ gBattleMons [ sBattler_AI ] . moves [ i ] ] . effect = = gAIScriptPtr [ 2 ] )
2017-02-04 03:34:56 +01:00
break ;
}
2018-12-25 18:50:15 +01:00
if ( i ! = MAX_MON_MOVES )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 7 ;
else
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
break ;
2017-09-05 13:01:24 +02:00
case AI_TARGET :
case AI_TARGET_PARTNER :
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] & & gBattleMoves [ BATTLE_HISTORY - > usedMoves [ gBattlerTarget ] . moves [ i ] ] . effect = = gAIScriptPtr [ 2 ] )
2017-02-04 03:34:56 +01:00
break ;
}
2018-12-25 18:50:15 +01:00
if ( i ! = MAX_MON_MOVES )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 7 ;
else
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
break ;
}
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_any_move_disabled_or_encored ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
if ( gAIScriptPtr [ 2 ] = = 0 )
{
2018-06-17 16:48:58 +02:00
if ( gDisableStructs [ battlerId ] . disabledMove = = MOVE_NONE )
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 7 ;
2018-06-17 16:48:58 +02:00
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
else if ( gAIScriptPtr [ 2 ] ! = 1 )
2017-02-04 03:34:56 +01:00
{
gAIScriptPtr + = 7 ;
}
2018-06-17 16:48:58 +02:00
else
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
if ( gDisableStructs [ battlerId ] . encoredMove ! = MOVE_NONE )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
else
gAIScriptPtr + = 7 ;
2017-02-04 03:34:56 +01:00
}
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_curr_move_disabled_or_encored ( void )
2017-02-04 03:34:56 +01:00
{
switch ( gAIScriptPtr [ 1 ] )
{
2017-09-05 09:41:48 +02:00
case 0 :
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . disabledMove = = AI_THINKING_STRUCT - > moveConsidered )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-06-17 16:48:58 +02:00
else
gAIScriptPtr + = 6 ;
2018-07-16 20:47:30 +02:00
break ;
2017-09-05 09:41:48 +02:00
case 1 :
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . encoredMove = = AI_THINKING_STRUCT - > moveConsidered )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-06-17 16:48:58 +02:00
else
gAIScriptPtr + = 6 ;
break ;
2017-02-04 03:34:56 +01:00
default :
gAIScriptPtr + = 6 ;
2018-06-17 16:48:58 +02:00
break ;
2017-02-04 03:34:56 +01:00
}
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_flee ( void )
2017-02-04 03:34:56 +01:00
{
2017-10-09 13:41:07 +02:00
AI_THINKING_STRUCT - > aiAction | = ( AI_ACTION_DONE | AI_ACTION_FLEE | AI_ACTION_DO_NOT_ATTACK ) ;
2017-02-04 03:34:56 +01:00
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_random_safari_flee ( void )
2017-02-04 03:34:56 +01:00
{
2018-07-01 11:15:42 +02:00
u8 safariFleeRate = gBattleStruct - > safariEscapeFactor * 5 ; // Safari flee rate, from 0-20.
2017-02-04 03:34:56 +01:00
if ( ( u8 ) ( Random ( ) % 100 ) < safariFleeRate )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 5 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_watch ( void )
2017-02-04 03:34:56 +01:00
{
2017-10-09 13:41:07 +02:00
AI_THINKING_STRUCT - > aiAction | = ( AI_ACTION_DONE | AI_ACTION_WATCH | AI_ACTION_DO_NOT_ATTACK ) ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_hold_effect ( void )
2017-02-04 03:34:56 +01:00
{
2019-05-20 12:03:00 +02:00
u32 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
2019-05-20 12:03:00 +02:00
if ( ! IsBattlerAIControlled ( battlerId ) )
AI_THINKING_STRUCT - > funcResult = BATTLE_HISTORY - > itemEffects [ battlerId ] ;
2017-02-04 03:34:56 +01:00
else
2019-05-20 12:03:00 +02:00
AI_THINKING_STRUCT - > funcResult = GetBattlerHoldEffect ( battlerId , FALSE ) ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_holds_item ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-02-04 03:34:56 +01:00
u16 item ;
2017-09-04 21:43:13 +02:00
2018-02-28 19:37:48 +01:00
if ( ( battlerId & BIT_SIDE ) = = ( sBattler_AI & BIT_SIDE ) )
item = gBattleMons [ battlerId ] . item ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
item = BATTLE_HISTORY - > itemEffects [ battlerId ] ;
2017-02-04 03:34:56 +01:00
2018-09-02 15:50:18 +02:00
if ( T1_READ_16 ( gAIScriptPtr + 2 ) = = item )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 4 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 8 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_gender ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerId ] . species , gBattleMons [ battlerId ] . personality ) ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_is_first_turn_for ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gDisableStructs [ battlerId ] . isFirstTurn ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_stockpile_count ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gDisableStructs [ battlerId ] . stockpileCounter ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_is_double_battle ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleTypeFlags & BATTLE_TYPE_DOUBLE ;
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_used_held_item ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-08-11 12:16:00 +02:00
AI_THINKING_STRUCT - > funcResult = gBattleStruct - > usedHeldItems [ battlerId ] ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_move_type_from_result ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > funcResult ] . type ;
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_move_power_from_result ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > funcResult ] . power ;
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_move_effect_from_result ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > funcResult ] . effect ;
gAIScriptPtr + = 1 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_get_protect_count ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-28 19:37:48 +01:00
battlerId = sBattler_AI ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
battlerId = gBattlerTarget ;
2017-02-04 03:34:56 +01:00
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gDisableStructs [ battlerId ] . protectUses ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2018-07-14 12:54:12 +02:00
static void BattleAICmd_if_move_flag ( void )
2017-02-04 03:34:56 +01:00
{
2018-09-02 15:50:18 +02:00
u32 flag = T1_READ_32 ( gAIScriptPtr + 1 ) ;
2018-07-14 12:54:12 +02:00
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . flags & flag )
2018-09-02 15:50:18 +02:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2018-07-14 12:54:12 +02:00
else
2018-09-02 15:50:18 +02:00
gAIScriptPtr + = 9 ;
2017-02-04 03:34:56 +01:00
}
2018-07-14 16:41:14 +02:00
static void BattleAICmd_if_field_status ( void )
2017-02-04 03:34:56 +01:00
{
2018-07-14 16:41:14 +02:00
u32 fieldFlags = T1_READ_32 ( gAIScriptPtr + 1 ) ;
if ( gFieldStatuses & fieldFlags )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
else
gAIScriptPtr + = 9 ;
2017-02-04 03:34:56 +01:00
}
2018-08-11 12:16:00 +02:00
static void BattleAICmd_get_move_accuracy ( void )
2017-02-04 03:34:56 +01:00
{
2018-08-11 12:16:00 +02:00
AI_THINKING_STRUCT - > funcResult = gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . accuracy ;
gAIScriptPtr + + ;
2017-02-04 03:34:56 +01:00
}
2018-08-11 12:16:00 +02:00
static void BattleAICmd_call_if_eq ( void )
2017-02-04 03:34:56 +01:00
{
2018-08-11 12:16:00 +02:00
if ( AI_THINKING_STRUCT - > funcResult = = T1_READ_16 ( gAIScriptPtr + 1 ) )
{
AIStackPushVar ( gAIScriptPtr + 7 ) ;
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
}
else
{
gAIScriptPtr + = 7 ;
}
2017-02-04 03:34:56 +01:00
}
2018-08-11 12:16:00 +02:00
static void BattleAICmd_call_if_move_flag ( void )
2017-02-04 03:34:56 +01:00
{
2018-09-02 15:50:18 +02:00
u32 flag = T1_READ_32 ( gAIScriptPtr + 1 ) ;
2018-08-11 12:16:00 +02:00
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . flags & flag )
{
2018-09-02 15:50:18 +02:00
AIStackPushVar ( gAIScriptPtr + 9 ) ;
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 5 ) ;
2018-08-11 12:16:00 +02:00
}
else
{
2018-09-02 15:50:18 +02:00
gAIScriptPtr + = 9 ;
2018-08-11 12:16:00 +02:00
}
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_57 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_call ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-05 09:41:48 +02:00
AIStackPushVar ( gAIScriptPtr + 5 ) ;
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_goto ( void )
2017-02-04 03:34:56 +01:00
{
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_end ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-05 09:41:48 +02:00
if ( AIStackPop ( ) = = 0 )
AI_THINKING_STRUCT - > aiAction | = AI_ACTION_DONE ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_level_cond ( void )
2017-02-04 03:34:56 +01:00
{
switch ( gAIScriptPtr [ 1 ] )
{
case 0 : // greater than
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . level > gBattleMons [ gBattlerTarget ] . level )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-06-17 16:48:58 +02:00
else
gAIScriptPtr + = 6 ;
break ;
2017-02-04 03:34:56 +01:00
case 1 : // less than
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . level < gBattleMons [ gBattlerTarget ] . level )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-06-17 16:48:58 +02:00
else
gAIScriptPtr + = 6 ;
break ;
2017-02-04 03:34:56 +01:00
case 2 : // equal
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . level = = gBattleMons [ gBattlerTarget ] . level )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-06-17 16:48:58 +02:00
else
gAIScriptPtr + = 6 ;
break ;
2017-02-04 03:34:56 +01:00
}
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_target_taunted ( void )
2017-02-04 03:34:56 +01:00
{
2018-10-14 18:10:54 +02:00
if ( gDisableStructs [ gBattlerTarget ] . tauntTimer ! = 0 )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 5 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_target_not_taunted ( void )
2017-02-04 03:34:56 +01:00
{
2018-10-14 18:10:54 +02:00
if ( gDisableStructs [ gBattlerTarget ] . tauntTimer = = 0 )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 5 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_target_is_ally ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( ( sBattler_AI & BIT_SIDE ) = = ( gBattlerTarget & BIT_SIDE ) )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 5 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_flash_fired ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
2017-09-04 21:43:13 +02:00
2018-07-19 21:18:20 +02:00
if ( gBattleResources - > flags - > flags [ battlerId ] & RESOURCE_FLAG_FLASH_FIRE )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-17 14:10:32 +02:00
static void AIStackPushVar ( const u8 * var )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
gBattleResources - > AI_ScriptsStack - > ptr [ gBattleResources - > AI_ScriptsStack - > size + + ] = var ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void AIStackPushVar_cursor ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
gBattleResources - > AI_ScriptsStack - > ptr [ gBattleResources - > AI_ScriptsStack - > size + + ] = gAIScriptPtr ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static bool8 AIStackPop ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
if ( gBattleResources - > AI_ScriptsStack - > size ! = 0 )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
- - gBattleResources - > AI_ScriptsStack - > size ;
gAIScriptPtr = gBattleResources - > AI_ScriptsStack - > ptr [ gBattleResources - > AI_ScriptsStack - > size ] ;
2017-02-04 03:34:56 +01:00
return TRUE ;
}
else
2018-06-17 16:48:58 +02:00
{
2017-02-04 03:34:56 +01:00
return FALSE ;
2018-06-17 16:48:58 +02:00
}
2017-02-04 03:34:56 +01:00
}
2018-09-01 17:36:09 +02:00
static void BattleAICmd_get_ally_chosen_move ( void )
{
u8 partnerBattler = BATTLE_PARTNER ( sBattler_AI ) ;
if ( ! IsBattlerAlive ( partnerBattler ) | | ! IsBattlerAIControlled ( partnerBattler ) )
AI_THINKING_STRUCT - > funcResult = 0 ;
else if ( partnerBattler > sBattler_AI ) // Battler with the lower id chooses the move first.
AI_THINKING_STRUCT - > funcResult = 0 ;
else
AI_THINKING_STRUCT - > funcResult = gBattleMons [ partnerBattler ] . moves [ gBattleStruct - > chosenMovePositions [ partnerBattler ] ] ;
gAIScriptPtr + + ;
}
static void BattleAICmd_if_has_no_attacking_moves ( void )
{
s32 i ;
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
if ( IsBattlerAIControlled ( battlerId ) )
{
for ( i = 0 ; i < 4 ; i + + )
{
if ( gBattleMons [ battlerId ] . moves [ i ] ! = 0 & & gBattleMoves [ gBattleMons [ battlerId ] . moves [ i ] ] . power ! = 0 )
break ;
}
}
else
{
for ( i = 0 ; i < 4 ; i + + )
{
if ( BATTLE_HISTORY - > usedMoves [ battlerId ] . moves [ i ] ! = 0 & & gBattleMoves [ BATTLE_HISTORY - > usedMoves [ battlerId ] . moves [ i ] ] . power ! = 0 )
break ;
}
}
if ( i = = 4 )
2018-09-02 15:50:18 +02:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-09-01 17:36:09 +02:00
else
2018-09-02 15:50:18 +02:00
gAIScriptPtr + = 6 ;
}
static void BattleAICmd_get_hazards_count ( void )
{
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u8 side = GetBattlerSide ( battlerId ) ;
switch ( T1_READ_16 ( gAIScriptPtr + 2 ) )
{
case EFFECT_SPIKES :
AI_THINKING_STRUCT - > funcResult = gSideTimers [ side ] . spikesAmount ;
break ;
case EFFECT_TOXIC_SPIKES :
AI_THINKING_STRUCT - > funcResult = gSideTimers [ side ] . toxicSpikesAmount ;
break ;
}
gAIScriptPtr + = 4 ;
}
static void BattleAICmd_if_doesnt_hold_berry ( void )
{
u8 battlerId = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u16 item ;
if ( IsBattlerAIControlled ( battlerId ) )
item = gBattleMons [ battlerId ] . item ;
else
item = BATTLE_HISTORY - > itemEffects [ battlerId ] ;
if ( ItemId_GetPocket ( item ) = = POCKET_BERRIES )
gAIScriptPtr + = 6 ;
else
2018-11-24 13:29:10 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2018-09-01 17:36:09 +02:00
}
2018-12-02 23:50:51 +01:00
static void BattleAICmd_if_share_type ( void )
{
u8 battler1 = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u8 battler2 = BattleAI_GetWantedBattler ( gAIScriptPtr [ 2 ] ) ;
if ( DoBattlersShareType ( battler1 , battler2 ) )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
else
gAIScriptPtr + = 7 ;
}
static void BattleAICmd_if_cant_use_last_resort ( void )
{
u8 battler = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
if ( CanUseLastResort ( battler ) )
gAIScriptPtr + = 6 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
}
2019-02-09 13:21:32 +01:00
static bool32 HasMoveWithSplit ( u32 battler , u32 split )
{
s32 i ;
u16 * moves ;
if ( IsBattlerAIControlled ( battler ) | | IsBattlerAIControlled ( BATTLE_PARTNER ( battler ) ) )
moves = gBattleMons [ battler ] . moves ;
else
moves = gBattleResources - > battleHistory - > usedMoves [ battler ] . moves ;
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
{
if ( moves [ i ] ! = MOVE_NONE & & moves [ i ] ! = 0xFFFF & & gBattleMoves [ moves [ i ] ] . split = = split )
return TRUE ;
}
return FALSE ;
}
static void BattleAICmd_if_has_move_with_split ( void )
{
if ( HasMoveWithSplit ( BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) , gAIScriptPtr [ 2 ] ) )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
else
gAIScriptPtr + = 7 ;
}
static void BattleAICmd_if_has_no_move_with_split ( void )
{
if ( ! HasMoveWithSplit ( BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) , gAIScriptPtr [ 2 ] ) )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
else
gAIScriptPtr + = 7 ;
}
2019-02-09 16:45:02 +01:00
// This function checks if all physical/special moves are either unusable or unreasonable to use.
// Consider a pokemon boosting their attack against a ghost pokemon having only normal-type physical attacks.
static bool32 MovesWithSplitUnusable ( u32 attacker , u32 target , u32 split )
{
s32 i , moveType ;
u16 * moves ;
u32 usable = 0 ;
u32 unusable = CheckMoveLimitations ( attacker , 0 , 0xFF ) ;
if ( IsBattlerAIControlled ( attacker ) )
moves = gBattleMons [ attacker ] . moves ;
else
moves = gBattleResources - > battleHistory - > usedMoves [ attacker ] . moves ;
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
{
if ( moves [ i ] ! = MOVE_NONE
& & moves [ i ] ! = 0xFFFF
& & gBattleMoves [ moves [ i ] ] . split = = split
& & ! ( unusable & gBitTable [ i ] ) )
{
SetTypeBeforeUsingMove ( moves [ i ] , attacker ) ;
GET_MOVE_TYPE ( moves [ i ] , moveType ) ;
if ( CalcTypeEffectivenessMultiplier ( moves [ i ] , moveType , attacker , target , FALSE ) ! = 0 )
usable | = gBitTable [ i ] ;
}
}
return ( usable = = 0 ) ;
}
static void BattleAICmd_if_physical_moves_unusable ( void )
{
if ( MovesWithSplitUnusable ( BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) , BattleAI_GetWantedBattler ( gAIScriptPtr [ 2 ] ) , SPLIT_PHYSICAL ) )
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
else
gAIScriptPtr + = 7 ;
}
2019-02-16 14:54:17 +01:00
// Check if target has means to faint ai mon.
static void BattleAICmd_if_ai_can_go_down ( void )
{
s32 i , dmg ;
u32 unusable = CheckMoveLimitations ( gBattlerTarget , 0 , 0xFF & ~ MOVE_LIMITATION_PP ) ;
u16 * moves = gBattleResources - > battleHistory - > usedMoves [ gBattlerTarget ] . moves ;
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
{
if ( moves [ i ] ! = MOVE_NONE & & moves [ i ] ! = 0xFFFF & & ! ( unusable & gBitTable [ i ] )
& & AI_CalcDamage ( moves [ i ] , gBattlerTarget , sBattler_AI ) > = gBattleMons [ sBattler_AI ] . hp )
{
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 1 ) ;
return ;
}
}
gAIScriptPtr + = 5 ;
}
2019-02-16 18:23:56 +01:00
static void BattleAICmd_if_cant_use_belch ( void )
{
u32 battler = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
if ( gBattleStruct - > ateBerry [ battler & BIT_SIDE ] & gBitTable [ gBattlerPartyIndexes [ battler ] ] )
gAIScriptPtr + = 6 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
}
2019-05-20 10:10:00 +02:00
static void BattleAICmd_if_has_move_with_type ( void )
{
u32 i , moveType , battler = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u16 * moves ;
if ( IsBattlerAIControlled ( battler ) )
moves = gBattleMons [ battler ] . moves ;
else
moves = BATTLE_HISTORY - > usedMoves [ battler ] . moves ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( moves [ i ] = = MOVE_NONE )
continue ;
SetTypeBeforeUsingMove ( moves [ i ] , battler ) ;
GET_MOVE_TYPE ( moves [ i ] , moveType ) ;
if ( moveType = = gAIScriptPtr [ 2 ] )
break ;
}
if ( i = = 4 )
gAIScriptPtr + = 7 ;
else
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 3 ) ;
}
2019-05-20 12:03:00 +02:00
2019-05-23 11:41:35 +02:00
static void BattleAICmd_if_has_move_with_flag ( void )
{
u32 i , flag , battler = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
u16 * moves ;
if ( IsBattlerAIControlled ( battler ) )
moves = gBattleMons [ battler ] . moves ;
else
moves = BATTLE_HISTORY - > usedMoves [ battler ] . moves ;
flag = T1_READ_32 ( gAIScriptPtr + 2 ) ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( moves [ i ] ! = MOVE_NONE & & gBattleMoves [ moves [ i ] ] . flags & flag )
{
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 6 ) ;
return ;
}
}
gAIScriptPtr + = 10 ;
}
2019-05-20 12:03:00 +02:00
static void BattleAICmd_if_no_move_used ( void )
{
u32 i , battler = BattleAI_GetWantedBattler ( gAIScriptPtr [ 1 ] ) ;
if ( ! IsBattlerAIControlled ( battler ) )
{
for ( i = 0 ; i < 4 ; i + + )
{
if ( BATTLE_HISTORY - > usedMoves [ battler ] . moves [ i ] ! = 0 & & BATTLE_HISTORY - > usedMoves [ battler ] . moves [ i ] ! = 0xFFFF )
{
gAIScriptPtr + = 6 ;
return ;
}
}
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
}
else
{
gAIScriptPtr + = 6 ;
}
}