2017-02-02 05:15:38 +01:00
# include "global.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"
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 ) ;
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 ) ;
2017-12-30 12:19:02 +01:00
static void BattleAICmd_if_equal_ ( void ) ;
static void BattleAICmd_if_not_equal_ ( void ) ;
static void BattleAICmd_if_user_goes ( void ) ;
static void BattleAICmd_if_user_doesnt_go ( 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 ) ;
static void BattleAICmd_nullsub_52 ( void ) ;
static void BattleAICmd_nullsub_53 ( void ) ;
static void BattleAICmd_nullsub_54 ( void ) ;
static void BattleAICmd_nullsub_55 ( void ) ;
static void BattleAICmd_nullsub_56 ( void ) ;
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 ) ;
// 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
BattleAICmd_if_equal_ , // 0x26
BattleAICmd_if_not_equal_ , // 0x27
BattleAICmd_if_user_goes , // 0x28
BattleAICmd_if_user_doesnt_go , // 0x29
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
BattleAICmd_nullsub_52 , // 0x52
BattleAICmd_nullsub_53 , // 0x53
BattleAICmd_nullsub_54 , // 0x54
BattleAICmd_nullsub_55 , // 0x55
BattleAICmd_nullsub_56 , // 0x56
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
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_RAZOR_WIND ,
EFFECT_SKY_ATTACK ,
EFFECT_RECHARGE ,
EFFECT_SKULL_BASH ,
EFFECT_SOLARBEAM ,
EFFECT_SPIT_UP ,
EFFECT_FOCUS_PUNCH ,
EFFECT_SUPERPOWER ,
EFFECT_ERUPTION ,
EFFECT_OVERHEAT ,
2018-12-05 15:31:01 +01:00
0xFFFF
2017-09-05 09:41:48 +02:00
} ;
2017-02-02 05:15:38 +01:00
2018-06-17 16:48:58 +02:00
// code
2017-09-05 09:41:48 +02:00
void BattleAI_HandleItemUseBeforeAISetup ( u8 defaultScoreMoves )
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
}
}
}
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
BattleAI_SetupAIData ( defaultScoreMoves ) ;
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-02-04 03:34:56 +01:00
u8 * data = ( u8 * ) AI_THINKING_STRUCT ;
2017-09-05 09:41:48 +02:00
u8 moveLimitations ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Clear AI data.
2017-09-05 09:41:48 +02:00
for ( i = 0 ; i < sizeof ( struct AI_ThinkingStruct ) ; i + + )
2017-02-02 05:15:38 +01:00
data [ i ] = 0 ;
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-09-05 09:41:48 +02:00
2018-06-17 16:48:58 +02:00
// Choose proper trainer ai scripts.
2017-09-05 09:41:48 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
AI_THINKING_STRUCT - > aiFlags = GetAiScriptsInRecordedBattle ( ) ;
else if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_SAFARI ;
2017-09-05 09:41:48 +02:00
else if ( gBattleTypeFlags & BATTLE_TYPE_ROAMER )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_ROAMING ;
2017-09-05 09:41:48 +02:00
else if ( gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_FIRST_BATTLE ;
2017-09-05 09:41:48 +02:00
else if ( gBattleTypeFlags & BATTLE_TYPE_FACTORY )
AI_THINKING_STRUCT - > aiFlags = GetAiScriptsInBattleFactory ( ) ;
2018-09-20 22:00:00 +02:00
else if ( gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE ) )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_CHECK_VIABILITY | AI_SCRIPT_TRY_TO_FAINT ;
2017-09-05 09:41:48 +02:00
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 ;
2018-06-17 16:48:58 +02:00
2017-09-05 09:41:48 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
2017-12-30 16:04:31 +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
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 ;
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
while ( AI_THINKING_STRUCT - > aiFlags ! = 0 )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
if ( AI_THINKING_STRUCT - > aiFlags & 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 ( ) ;
}
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiFlags > > = 1 ;
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
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 ;
2017-09-08 18:19:20 +02:00
s32 scriptsToRun ;
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 ;
2018-12-09 04:32:58 +01: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 ;
scriptsToRun = AI_THINKING_STRUCT - > aiFlags ;
while ( scriptsToRun ! = 0 )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
if ( scriptsToRun & 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 ( ) ;
}
2017-09-08 18:19:20 +02:00
scriptsToRun > > = 1 ;
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
{
2018-12-05 15:31:01 +01: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 ;
}
}
}
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
}
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.
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_if_hp_less_than ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u16 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 ( ( 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
{
2018-02-28 19:37:48 +01:00
u16 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 ( ( 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
{
2018-02-28 19:37:48 +01:00
u16 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 ( ( 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
{
2018-02-28 19:37:48 +01:00
u16 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 ( ( 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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 status ;
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-03-01 00:59:52 +01:00
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 status ;
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-03-01 00:59:52 +01:00
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 status ;
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-03-01 00:59:52 +01:00
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 status ;
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-03-01 00:59:52 +01:00
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 status ;
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-03-01 00:59:52 +01:00
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 status ;
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-03-01 00:59:52 +01:00
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 side , status ;
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
side = GET_BATTLER_SIDE ( battlerId ) ;
2018-03-01 00:59:52 +01:00
status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
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
{
2018-02-28 19:37:48 +01:00
u16 battlerId ;
2017-12-24 19:08:55 +01:00
u32 side , status ;
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
side = GET_BATTLER_SIDE ( battlerId ) ;
2018-03-01 00:59:52 +01:00
status = T1_READ_32 ( gAIScriptPtr + 2 ) ;
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
2018-12-05 15:31:01 +01:00
while ( * ptr ! = 0xFF )
2017-02-04 03:34:56 +01:00
{
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
2018-12-05 15:31:01 +01:00
while ( * ptr ! = 0xFF )
2017-02-04 03:34:56 +01:00
{
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
2018-12-05 15:31:01 +01:00
while ( * ptr ! = 0xFFFF )
2017-02-04 03:34:56 +01:00
{
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
2018-12-05 15:31:01 +01:00
while ( * ptr ! = 0xFFFF )
2017-02-04 03:34:56 +01:00
{
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 ;
}
2018-06-17 16:48:58 +02:00
static u8 BattleAI_GetWantedBattler ( u8 wantedBattler )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
switch ( wantedBattler )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
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
}
}
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 ] ;
2018-12-05 15:31:01 +01:00
for ( i = 0 ; sDiscouragedPowerfulMoveEffects [ i ] ! = 0xFFFF ; i + + )
2017-10-09 13:41:07 +02:00
{
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect = = sDiscouragedPowerfulMoveEffects [ i ] )
break ;
}
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power > 1
2018-12-05 15:31:01 +01:00
& & sDiscouragedPowerfulMoveEffects [ i ] = = 0xFFFF )
2017-10-09 13:41:07 +02:00
{
gDynamicBasePower = 0 ;
* ( & gBattleStruct - > dynamicMoveType ) = 0 ;
gBattleScripting . dmgMultiplier = 1 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-10-09 13:41:07 +02:00
gCritMultiplier = 1 ;
2018-12-25 18:50:15 +01:00
for ( checkedMove = 0 ; checkedMove < MAX_MON_MOVES ; checkedMove + + )
2017-10-09 13:41:07 +02:00
{
2018-12-05 15:31:01 +01:00
for ( i = 0 ; sDiscouragedPowerfulMoveEffects [ i ] ! = 0xFFFF ; i + + )
2017-10-09 13:41:07 +02:00
{
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
2018-12-05 15:31:01 +01: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 ] ;
AI_CalcDmg ( sBattler_AI , gBattlerTarget ) ;
TypeCalc ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
2017-10-09 13:41:07 +02:00
moveDmgs [ checkedMove ] = gBattleMoveDamage * AI_THINKING_STRUCT - > simulatedRNG [ checkedMove ] / 100 ;
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 ;
}
2018-06-17 16:48:58 +02:00
static void BattleAICmd_if_equal_ ( void ) // Same as if_equal.
2017-02-04 03:34:56 +01:00
{
if ( gAIScriptPtr [ 1 ] = = AI_THINKING_STRUCT - > funcResult )
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 ;
}
2018-06-17 16:48:58 +02:00
static void BattleAICmd_if_not_equal_ ( void ) // Same as if_not_equal.
2017-02-04 03:34:56 +01:00
{
if ( gAIScriptPtr [ 1 ] ! = AI_THINKING_STRUCT - > funcResult )
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-12-30 12:19:02 +01:00
static void BattleAICmd_if_user_goes ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( GetWhoStrikesFirst ( sBattler_AI , gBattlerTarget , TRUE ) = = 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-12-30 12:19:02 +01:00
static void BattleAICmd_if_user_doesnt_go ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
if ( GetWhoStrikesFirst ( sBattler_AI , gBattlerTarget , TRUE ) ! = 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_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
{
}
2017-12-30 12:19:02 +01:00
static void BattleAICmd_count_usable_party_mons ( void )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2018-06-17 16:48:58 +02:00
u8 battlerOnField1 , battlerOnField2 ;
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
AI_THINKING_STRUCT - > funcResult = 0 ;
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 ( GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
2017-02-04 03:34:56 +01:00
party = gPlayerParty ;
else
party = gEnemyParty ;
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
2018-01-16 23:42:31 +01:00
u32 position ;
2018-06-17 16:48:58 +02:00
battlerOnField1 = gBattlerPartyIndexes [ battlerId ] ;
2018-02-28 19:37:48 +01:00
position = GetBattlerPosition ( battlerId ) ^ BIT_FLANK ;
2018-06-17 16:48:58 +02:00
battlerOnField2 = gBattlerPartyIndexes [ GetBattlerAtPosition ( position ) ] ;
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
}
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 )
{
AI_THINKING_STRUCT - > funcResult + + ;
}
}
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
{
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
if ( gActiveBattler ! = 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 ;
}
2018-02-28 19:37:48 +01:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . ability2 ! = 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 )
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability2 ;
2017-09-04 21:43:13 +02:00
}
2017-02-04 03:34:56 +01:00
else
{
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ; // It's definitely ability 1.
2017-02-04 03:34:56 +01:00
}
}
else
{
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability2 ; // 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
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_TARGET | | gAIScriptPtr [ 1 ] = = AI_TARGET_PARTNER )
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
}
2018-02-28 19:37:48 +01:00
else if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ! = ABILITY_NONE )
2017-09-05 09:41:48 +02:00
{
2018-02-28 19:37:48 +01:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . ability2 ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u8 abilityDummyVariable = ability ; // Needed to match.
2018-02-28 19:37:48 +01:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ! = abilityDummyVariable
& & gBaseStats [ gBattleMons [ battlerId ] . species ] . ability2 ! = abilityDummyVariable )
2017-02-04 03:34:56 +01:00
{
2018-02-28 19:37:48 +01:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ;
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
{
2018-02-28 19:37:48 +01:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability1 ;
2017-02-04 03:34:56 +01:00
}
}
2017-09-05 09:41:48 +02:00
else
{
2018-06-17 16:48:58 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . ability2 ; // 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
2017-09-05 09:41:48 +02:00
gDynamicBasePower = 0 ;
dynamicMoveType = & gBattleStruct - > dynamicMoveType ;
* dynamicMoveType = 0 ;
gBattleScripting . dmgMultiplier = 1 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-02-04 03:34:56 +01:00
gCritMultiplier = 1 ;
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-06-17 16:48:58 +02:00
gBattleMoveDamage = 40 ;
2018-02-06 23:09:39 +01:00
gCurrentMove = gBattleMons [ sBattler_AI ] . moves [ i ] ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( gCurrentMove ! = MOVE_NONE )
2017-02-04 03:34:56 +01:00
{
2018-02-06 23:09:39 +01:00
TypeCalc ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( gBattleMoveDamage = = 120 ) // Super effective STAB.
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x2 ;
2017-02-04 03:34:56 +01:00
if ( gBattleMoveDamage = = 240 )
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x4 ;
2018-06-17 16:48:58 +02:00
if ( gBattleMoveDamage = = 30 ) // Not very effective STAB.
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x0_5 ;
2017-02-04 03:34:56 +01:00
if ( gBattleMoveDamage = = 15 )
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x0_25 ;
2017-02-04 03:34:56 +01:00
2018-01-16 22:12:38 +01:00
if ( gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE )
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x0 ;
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 ;
2017-09-05 09:41:48 +02:00
gDynamicBasePower = 0 ;
gBattleStruct - > dynamicMoveType = 0 ;
gBattleScripting . dmgMultiplier = 1 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-02-04 03:34:56 +01:00
gCritMultiplier = 1 ;
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x1 ;
2017-08-31 16:48:24 +02:00
gCurrentMove = AI_THINKING_STRUCT - > moveConsidered ;
2017-02-04 03:34:56 +01:00
2018-02-06 23:09:39 +01:00
TypeCalc ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( gBattleMoveDamage = = 120 ) // Super effective STAB.
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x2 ;
2017-02-04 03:34:56 +01:00
if ( gBattleMoveDamage = = 240 )
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x4 ;
2018-06-17 16:48:58 +02:00
if ( gBattleMoveDamage = = 30 ) // Not very effective STAB.
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x0_5 ;
2017-02-04 03:34:56 +01:00
if ( gBattleMoveDamage = = 15 )
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x0_25 ;
2017-02-04 03:34:56 +01:00
2018-01-16 22:12:38 +01:00
if ( gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE )
2017-12-30 16:04:31 +01:00
gBattleMoveDamage = AI_EFFECTIVENESS_x0 ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Store gBattleMoveDamage in a u8 variable because gAIScriptPtr[1] is a u8.
2017-02-04 03:34:56 +01:00
damageVar = gBattleMoveDamage ;
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 ;
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
switch ( gAIScriptPtr [ 1 ] )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
case AI_USER :
battlerId = sBattler_AI ;
break ;
default :
battlerId = gBattlerTarget ;
break ;
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 ;
2018-02-28 19:37:48 +01:00
u8 battlerId ;
2017-02-04 03:34:56 +01:00
switch ( gAIScriptPtr [ 1 ] )
{
2018-06-17 16:48:58 +02:00
case 1 :
battlerId = sBattler_AI ;
break ;
default :
battlerId = gBattlerTarget ;
break ;
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-06-17 16:48:58 +02:00
gAIScriptPtr + = 10 ; // UB: Still bugged in Emerald. Uncomment the return statement to fix.
// 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 ;
2017-09-05 09:41:48 +02:00
if ( gBattleWeather & WEATHER_SANDSTORM_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_SANDSTORM ;
2017-09-05 09:41:48 +02:00
if ( gBattleWeather & WEATHER_SUN_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_SUN ;
2017-09-05 09:41:48 +02:00
if ( gBattleWeather & WEATHER_HAIL_ANY )
2017-12-30 16:04:31 +01:00
AI_THINKING_STRUCT - > funcResult = AI_WEATHER_HAIL ;
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
{
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect = = 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_effect ( void )
2017-02-04 03:34:56 +01:00
{
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . effect ! = 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_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
{
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power < 2 )
{
gAIScriptPtr + = 5 ;
return ;
}
2017-09-05 09:41:48 +02:00
gDynamicBasePower = 0 ;
gBattleStruct - > dynamicMoveType = 0 ;
gBattleScripting . dmgMultiplier = 1 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-02-04 03:34:56 +01:00
gCritMultiplier = 1 ;
2017-08-31 16:48:24 +02:00
gCurrentMove = AI_THINKING_STRUCT - > moveConsidered ;
2018-02-06 23:09:39 +01:00
AI_CalcDmg ( sBattler_AI , gBattlerTarget ) ;
TypeCalc ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
2017-02-04 03:34:56 +01:00
2017-09-05 09:41:48 +02:00
gBattleMoveDamage = gBattleMoveDamage * 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.
2017-02-04 03:34:56 +01:00
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerTarget ] . hp < = gBattleMoveDamage )
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
{
if ( gBattleMoves [ AI_THINKING_STRUCT - > moveConsidered ] . power < 2 )
{
gAIScriptPtr + = 5 ;
return ;
}
2017-09-05 09:41:48 +02:00
gDynamicBasePower = 0 ;
gBattleStruct - > dynamicMoveType = 0 ;
gBattleScripting . dmgMultiplier = 1 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-02-04 03:34:56 +01:00
gCritMultiplier = 1 ;
2017-08-31 16:48:24 +02:00
gCurrentMove = AI_THINKING_STRUCT - > moveConsidered ;
2018-02-06 23:09:39 +01:00
AI_CalcDmg ( sBattler_AI , gBattlerTarget ) ;
TypeCalc ( gCurrentMove , sBattler_AI , gBattlerTarget ) ;
2017-02-04 03:34:56 +01:00
2017-09-05 09:41:48 +02:00
gBattleMoveDamage = gBattleMoveDamage * 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
// This macro is missing the damage 0 = 1 assumption.
2017-02-04 03:34:56 +01:00
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ gBattlerTarget ] . hp > gBattleMoveDamage )
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-06-17 16:48:58 +02:00
// UB: checks sBattler_AI instead of gBattlerTarget.
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . 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
{
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
if ( gActiveBattler ! = battlerId )
AI_THINKING_STRUCT - > funcResult = ItemId_GetHoldEffect ( BATTLE_HISTORY - > itemEffects [ battlerId ] ) ;
2017-02-04 03:34:56 +01:00
else
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = ItemId_GetHoldEffect ( gBattleMons [ battlerId ] . item ) ;
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 ;
u8 var1 , var2 ;
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
2017-09-05 09:41:48 +02:00
// UB: doesn't properly read an unaligned u16
2017-02-04 03:34:56 +01:00
var2 = gAIScriptPtr [ 2 ] ;
var1 = gAIScriptPtr [ 3 ] ;
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
if ( ( var1 | var2 ) = = 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-06-17 16:48:58 +02:00
// This is likely a leftover from Ruby's code and its ugly ewram access.
2017-09-05 09:41:48 +02:00
# ifdef NONMATCHING
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleStruct - > usedHeldItems [ battlerId ] ;
2017-09-05 09:41:48 +02:00
# else
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = * ( u8 * ) ( ( u8 * ) ( gBattleStruct ) + offsetof ( struct BattleStruct , usedHeldItems ) + ( battlerId * 2 ) ) ;
2017-09-05 09:41:48 +02:00
# endif // NONMATCHING
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 ;
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_52 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_53 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_54 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_55 ( void )
2017-02-04 03:34:56 +01:00
{
}
2017-09-05 09:41:48 +02:00
static void BattleAICmd_nullsub_56 ( void )
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-02-28 19:37:48 +01:00
if ( gBattleResources - > flags - > flags [ battlerId ] & UNKNOWN_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
}