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"
2019-04-04 23:53:06 +02:00
# include "data.h"
2017-09-05 09:41:48 +02:00
# include "item.h"
2018-11-14 01:01:50 +01:00
# include "pokemon.h"
# include "random.h"
# include "recorded_battle.h"
2018-11-11 16:44:27 +01:00
# include "util.h"
# include "constants/abilities.h"
2018-11-14 01:01:50 +01:00
# include "constants/battle_ai.h"
2017-12-05 18:55:48 +01:00
# include "constants/battle_move_effects.h"
2017-12-11 19:27:51 +01:00
# include "constants/moves.h"
2017-02-02 05:15:38 +01:00
2017-09-05 09:41:48 +02:00
# define AI_ACTION_DONE 0x0001
# define AI_ACTION_FLEE 0x0002
# define AI_ACTION_WATCH 0x0004
# define AI_ACTION_DO_NOT_ATTACK 0x0008
2017-02-04 03:34:56 +01:00
# define AI_ACTION_UNK5 0x0010
# define AI_ACTION_UNK6 0x0020
# define AI_ACTION_UNK7 0x0040
# define AI_ACTION_UNK8 0x0080
2017-09-05 09:41:48 +02:00
# define AI_THINKING_STRUCT ((struct AI_ThinkingStruct *)(gBattleResources->ai))
# define BATTLE_HISTORY ((struct BattleHistory *)(gBattleResources->battleHistory))
2017-02-04 03:34:56 +01:00
// AI states
enum
{
AIState_SettingUp ,
AIState_Processing ,
AIState_FinishedProcessing ,
AIState_DoNotProcess
} ;
/*
gAIScriptPtr is a pointer to the next battle AI cmd command to read .
when a command finishes processing , gAIScriptPtr is incremented by
the number of bytes that the current command had reserved for arguments
in order to read the next command correctly . refer to battle_ai_scripts . s for the
AI scripts .
*/
2018-06-17 16:48:58 +02:00
extern const u8 * const gBattleAI_ScriptsTable [ ] ;
2017-09-05 09:41:48 +02:00
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Singles ( void ) ;
static u8 ChooseMoveOrAction_Doubles ( void ) ;
2017-09-05 09:41:48 +02:00
static void RecordLastUsedMoveByTarget ( void ) ;
static void BattleAI_DoAIProcessing ( void ) ;
2017-09-17 14:10:32 +02:00
static void AIStackPushVar ( const u8 * ) ;
2017-09-05 09:41:48 +02:00
static bool8 AIStackPop ( void ) ;
2019-08-23 14:10:37 +02:00
static void Cmd_if_random_less_than ( void ) ;
static void Cmd_if_random_greater_than ( void ) ;
static void Cmd_if_random_equal ( void ) ;
static void Cmd_if_random_not_equal ( void ) ;
static void Cmd_score ( void ) ;
static void Cmd_if_hp_less_than ( void ) ;
static void Cmd_if_hp_more_than ( void ) ;
static void Cmd_if_hp_equal ( void ) ;
static void Cmd_if_hp_not_equal ( void ) ;
static void Cmd_if_status ( void ) ;
static void Cmd_if_not_status ( void ) ;
static void Cmd_if_status2 ( void ) ;
static void Cmd_if_not_status2 ( void ) ;
static void Cmd_if_status3 ( void ) ;
static void Cmd_if_not_status3 ( void ) ;
static void Cmd_if_side_affecting ( void ) ;
static void Cmd_if_not_side_affecting ( void ) ;
static void Cmd_if_less_than ( void ) ;
static void Cmd_if_more_than ( void ) ;
static void Cmd_if_equal ( void ) ;
static void Cmd_if_not_equal ( void ) ;
static void Cmd_if_less_than_ptr ( void ) ;
static void Cmd_if_more_than_ptr ( void ) ;
static void Cmd_if_equal_ptr ( void ) ;
static void Cmd_if_not_equal_ptr ( void ) ;
static void Cmd_if_move ( void ) ;
static void Cmd_if_not_move ( void ) ;
static void Cmd_if_in_bytes ( void ) ;
static void Cmd_if_not_in_bytes ( void ) ;
static void Cmd_if_in_hwords ( void ) ;
static void Cmd_if_not_in_hwords ( void ) ;
static void Cmd_if_user_has_attacking_move ( void ) ;
static void Cmd_if_user_has_no_attacking_moves ( void ) ;
static void Cmd_get_turn_count ( void ) ;
static void Cmd_get_type ( void ) ;
static void Cmd_get_considered_move_power ( void ) ;
static void Cmd_get_how_powerful_move_is ( void ) ;
static void Cmd_get_last_used_battler_move ( void ) ;
static void Cmd_if_equal_ ( void ) ;
static void Cmd_if_not_equal_ ( void ) ;
static void Cmd_if_user_goes ( void ) ;
static void Cmd_if_user_doesnt_go ( void ) ;
2021-01-23 05:22:37 +01:00
static void Cmd_nop_2A ( void ) ;
static void Cmd_nop_2B ( void ) ;
2019-08-23 14:10:37 +02:00
static void Cmd_count_usable_party_mons ( void ) ;
static void Cmd_get_considered_move ( void ) ;
static void Cmd_get_considered_move_effect ( void ) ;
static void Cmd_get_ability ( void ) ;
static void Cmd_get_highest_type_effectiveness ( void ) ;
static void Cmd_if_type_effectiveness ( void ) ;
2021-01-23 05:22:37 +01:00
static void Cmd_nop_32 ( void ) ;
static void Cmd_nop_33 ( void ) ;
2019-08-23 14:10:37 +02:00
static void Cmd_if_status_in_party ( void ) ;
static void Cmd_if_status_not_in_party ( void ) ;
static void Cmd_get_weather ( void ) ;
static void Cmd_if_effect ( void ) ;
static void Cmd_if_not_effect ( void ) ;
static void Cmd_if_stat_level_less_than ( void ) ;
static void Cmd_if_stat_level_more_than ( void ) ;
static void Cmd_if_stat_level_equal ( void ) ;
static void Cmd_if_stat_level_not_equal ( void ) ;
static void Cmd_if_can_faint ( void ) ;
static void Cmd_if_cant_faint ( void ) ;
static void Cmd_if_has_move ( void ) ;
static void Cmd_if_doesnt_have_move ( void ) ;
static void Cmd_if_has_move_with_effect ( void ) ;
static void Cmd_if_doesnt_have_move_with_effect ( void ) ;
static void Cmd_if_any_move_disabled_or_encored ( void ) ;
static void Cmd_if_curr_move_disabled_or_encored ( void ) ;
static void Cmd_flee ( void ) ;
static void Cmd_if_random_safari_flee ( void ) ;
static void Cmd_watch ( void ) ;
static void Cmd_get_hold_effect ( void ) ;
static void Cmd_get_gender ( void ) ;
static void Cmd_is_first_turn_for ( void ) ;
static void Cmd_get_stockpile_count ( void ) ;
static void Cmd_is_double_battle ( void ) ;
static void Cmd_get_used_held_item ( void ) ;
static void Cmd_get_move_type_from_result ( void ) ;
static void Cmd_get_move_power_from_result ( void ) ;
static void Cmd_get_move_effect_from_result ( void ) ;
static void Cmd_get_protect_count ( void ) ;
2021-01-23 05:22:37 +01:00
static void Cmd_nop_52 ( void ) ;
static void Cmd_nop_53 ( void ) ;
static void Cmd_nop_54 ( void ) ;
static void Cmd_nop_55 ( void ) ;
static void Cmd_nop_56 ( void ) ;
static void Cmd_nop_57 ( void ) ;
2019-08-23 14:10:37 +02:00
static void Cmd_call ( void ) ;
static void Cmd_goto ( void ) ;
static void Cmd_end ( void ) ;
static void Cmd_if_level_cond ( void ) ;
static void Cmd_if_target_taunted ( void ) ;
static void Cmd_if_target_not_taunted ( void ) ;
static void Cmd_check_ability ( void ) ;
static void Cmd_is_of_type ( void ) ;
static void Cmd_if_target_is_ally ( void ) ;
static void Cmd_if_flash_fired ( void ) ;
static void Cmd_if_holds_item ( void ) ;
2017-09-05 09:41:48 +02:00
// ewram
2017-09-17 14:10:32 +02:00
EWRAM_DATA const u8 * gAIScriptPtr = NULL ;
2018-02-06 23:09:39 +01:00
EWRAM_DATA static u8 sBattler_AI = 0 ;
2017-09-05 09:41:48 +02:00
// const rom data
2017-02-02 05:15:38 +01:00
typedef void ( * BattleAICmdFunc ) ( void ) ;
2017-09-05 09:41:48 +02:00
static const BattleAICmdFunc sBattleAICmdTable [ ] =
{
2019-08-23 14:10:37 +02:00
Cmd_if_random_less_than , // 0x0
Cmd_if_random_greater_than , // 0x1
Cmd_if_random_equal , // 0x2
Cmd_if_random_not_equal , // 0x3
Cmd_score , // 0x4
Cmd_if_hp_less_than , // 0x5
Cmd_if_hp_more_than , // 0x6
Cmd_if_hp_equal , // 0x7
Cmd_if_hp_not_equal , // 0x8
Cmd_if_status , // 0x9
Cmd_if_not_status , // 0xA
Cmd_if_status2 , // 0xB
Cmd_if_not_status2 , // 0xC
Cmd_if_status3 , // 0xD
Cmd_if_not_status3 , // 0xE
Cmd_if_side_affecting , // 0xF
Cmd_if_not_side_affecting , // 0x10
Cmd_if_less_than , // 0x11
Cmd_if_more_than , // 0x12
Cmd_if_equal , // 0x13
Cmd_if_not_equal , // 0x14
Cmd_if_less_than_ptr , // 0x15
Cmd_if_more_than_ptr , // 0x16
Cmd_if_equal_ptr , // 0x17
Cmd_if_not_equal_ptr , // 0x18
Cmd_if_move , // 0x19
Cmd_if_not_move , // 0x1A
Cmd_if_in_bytes , // 0x1B
Cmd_if_not_in_bytes , // 0x1C
Cmd_if_in_hwords , // 0x1D
Cmd_if_not_in_hwords , // 0x1E
Cmd_if_user_has_attacking_move , // 0x1F
Cmd_if_user_has_no_attacking_moves , // 0x20
Cmd_get_turn_count , // 0x21
Cmd_get_type , // 0x22
Cmd_get_considered_move_power , // 0x23
Cmd_get_how_powerful_move_is , // 0x24
Cmd_get_last_used_battler_move , // 0x25
Cmd_if_equal_ , // 0x26
Cmd_if_not_equal_ , // 0x27
Cmd_if_user_goes , // 0x28
Cmd_if_user_doesnt_go , // 0x29
2021-01-23 05:22:37 +01:00
Cmd_nop_2A , // 0x2A
Cmd_nop_2B , // 0x2B
2019-08-23 14:10:37 +02:00
Cmd_count_usable_party_mons , // 0x2C
Cmd_get_considered_move , // 0x2D
Cmd_get_considered_move_effect , // 0x2E
Cmd_get_ability , // 0x2F
Cmd_get_highest_type_effectiveness , // 0x30
Cmd_if_type_effectiveness , // 0x31
2021-01-23 05:22:37 +01:00
Cmd_nop_32 , // 0x32
Cmd_nop_33 , // 0x33
2019-08-23 14:10:37 +02:00
Cmd_if_status_in_party , // 0x34
Cmd_if_status_not_in_party , // 0x35
Cmd_get_weather , // 0x36
Cmd_if_effect , // 0x37
Cmd_if_not_effect , // 0x38
Cmd_if_stat_level_less_than , // 0x39
Cmd_if_stat_level_more_than , // 0x3A
Cmd_if_stat_level_equal , // 0x3B
Cmd_if_stat_level_not_equal , // 0x3C
Cmd_if_can_faint , // 0x3D
Cmd_if_cant_faint , // 0x3E
Cmd_if_has_move , // 0x3F
Cmd_if_doesnt_have_move , // 0x40
Cmd_if_has_move_with_effect , // 0x41
Cmd_if_doesnt_have_move_with_effect , // 0x42
Cmd_if_any_move_disabled_or_encored , // 0x43
Cmd_if_curr_move_disabled_or_encored , // 0x44
Cmd_flee , // 0x45
Cmd_if_random_safari_flee , // 0x46
Cmd_watch , // 0x47
Cmd_get_hold_effect , // 0x48
Cmd_get_gender , // 0x49
Cmd_is_first_turn_for , // 0x4A
Cmd_get_stockpile_count , // 0x4B
Cmd_is_double_battle , // 0x4C
Cmd_get_used_held_item , // 0x4D
Cmd_get_move_type_from_result , // 0x4E
Cmd_get_move_power_from_result , // 0x4F
Cmd_get_move_effect_from_result , // 0x50
Cmd_get_protect_count , // 0x51
2021-01-23 05:22:37 +01:00
Cmd_nop_52 , // 0x52
Cmd_nop_53 , // 0x53
Cmd_nop_54 , // 0x54
Cmd_nop_55 , // 0x55
Cmd_nop_56 , // 0x56
Cmd_nop_57 , // 0x57
2019-08-23 14:10:37 +02:00
Cmd_call , // 0x58
Cmd_goto , // 0x59
Cmd_end , // 0x5A
Cmd_if_level_cond , // 0x5B
Cmd_if_target_taunted , // 0x5C
Cmd_if_target_not_taunted , // 0x5D
Cmd_if_target_is_ally , // 0x5E
Cmd_is_of_type , // 0x5F
Cmd_check_ability , // 0x60
Cmd_if_flash_fired , // 0x61
Cmd_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
2021-01-13 21:17:32 +01:00
| BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED_LINK )
2018-06-17 16:48:58 +02:00
)
)
2017-02-02 05:15:38 +01:00
{
2019-09-08 18:21:24 +02:00
for ( i = 0 ; i < MAX_TRAINER_ITEMS ; i + + )
2017-02-02 05:15:38 +01:00
{
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
{
2019-09-08 17:53:48 +02:00
u8 currentMoveArray [ MAX_MON_MOVES ] ;
u8 consideredMoveArray [ MAX_MON_MOVES ] ;
2017-02-04 03:34:56 +01:00
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 ;
2020-11-08 00:21:17 +01:00
# ifndef BUGFIX
2017-09-08 18:19:20 +02:00
s32 scriptsToRun ;
2020-11-08 00:21:17 +01:00
# else
// the value assigned to this is a u32 (aiFlags)
// this becomes relevant because aiFlags can have bit 31 set
// and scriptsToRun is shifted
// this never happens in the vanilla game because bit 31 is
// only set when it's the first battle
u32 scriptsToRun ;
# endif
2019-09-08 17:53:48 +02:00
s16 bestMovePointsForTarget [ MAX_BATTLERS_COUNT ] ;
s8 mostViableTargetsArray [ MAX_BATTLERS_COUNT ] ;
u8 actionOrMoveIndex [ MAX_BATTLERS_COUNT ] ;
u8 mostViableMovesScores [ MAX_MON_MOVES ] ;
u8 mostViableMovesIndices [ MAX_MON_MOVES ] ;
2017-09-08 18:19:20 +02:00
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 )
2020-07-17 02:12:12 +02:00
BattleAI_SetupAIData ( gBattleStruct - > palaceFlags > > 4 ) ;
2017-02-02 05:15:38 +01:00
else
2020-07-17 02:12:12 +02:00
BattleAI_SetupAIData ( ( 1 < < MAX_MON_MOVES ) - 1 ) ;
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
2019-09-08 17:53:48 +02:00
for ( i = 1 ; i < MAX_BATTLERS_COUNT ; 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 ;
2020-09-17 04:01:45 +02:00
if ( 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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_score ( void )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] + = gAIScriptPtr [ 1 ] ; // Add the result to the array of the move consider's score.
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
if ( AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] < 0 ) // If the score is negative, flatten it to 0.
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] = 0 ;
gAIScriptPtr + = 2 ; // AI return.
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
2019-09-08 17:53:48 +02:00
s32 moveDmgs [ MAX_MON_MOVES ] ;
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
{
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
}
2019-08-23 14:10:37 +02:00
static void Cmd_get_last_used_battler_move ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-05 13:01:24 +02:00
if ( gAIScriptPtr [ 1 ] = = AI_USER )
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gLastMoves [ sBattler_AI ] ;
2017-02-04 03:34:56 +01:00
else
2018-02-06 23:09:39 +01:00
AI_THINKING_STRUCT - > funcResult = gLastMoves [ gBattlerTarget ] ;
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_2A ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_2B ( void )
2017-02-04 03:34:56 +01:00
{
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 )
{
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 09:22:50 +02:00
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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_get_considered_move ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = AI_THINKING_STRUCT - > moveConsidered ;
gAIScriptPtr + = 1 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
// AI has no knowledge of opponent, so it guesses which ability.
2017-09-05 09:41:48 +02:00
if ( Random ( ) & 1 )
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2017-02-04 03:34:56 +01:00
else
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ;
2017-09-04 21:43:13 +02:00
}
2017-02-04 03:34:56 +01:00
else
{
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ; // It's definitely ability 1.
2017-02-04 03:34:56 +01:00
}
}
else
{
2019-05-14 15:42:55 +02:00
AI_THINKING_STRUCT - > funcResult = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ; // AI can't actually reach this part since no pokemon has ability 2 and no ability 1.
2017-02-04 03:34:56 +01:00
}
}
else
{
// The AI knows its own ability.
2018-02-28 19:37:48 +01:00
AI_THINKING_STRUCT - > funcResult = gBattleMons [ battlerId ] . ability ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 2 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-05-14 15:42:55 +02:00
else if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ! = ABILITY_NONE )
2017-09-05 09:41:48 +02:00
{
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ! = ABILITY_NONE )
2017-02-04 03:34:56 +01:00
{
2018-06-17 16:48:58 +02:00
u8 abilityDummyVariable = ability ; // Needed to match.
2019-05-14 15:42:55 +02:00
if ( gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ! = abilityDummyVariable
& & gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ! = abilityDummyVariable )
2017-02-04 03:34:56 +01:00
{
2019-05-14 15:42:55 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2017-02-04 03:34:56 +01:00
}
else
2018-06-17 16:48:58 +02:00
{
ability = ABILITY_NONE ;
}
2017-09-05 09:41:48 +02:00
}
else
{
2019-05-14 15:42:55 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 0 ] ;
2017-02-04 03:34:56 +01:00
}
}
2017-09-05 09:41:48 +02:00
else
{
2019-05-14 15:42:55 +02:00
ability = gBaseStats [ gBattleMons [ battlerId ] . species ] . abilities [ 1 ] ; // AI can't actually reach this part since no pokemon has ability 2 and no ability 1.
2017-09-05 09:41:48 +02:00
}
2017-02-04 03:34:56 +01:00
}
else
{
2017-09-05 09:41:48 +02:00
// The AI knows its own or partner's ability.
2018-02-28 19:37:48 +01:00
ability = gBattleMons [ battlerId ] . ability ;
2017-02-04 03:34:56 +01:00
}
2018-06-17 16:48:58 +02:00
2017-09-05 09:41:48 +02:00
if ( ability = = 0 )
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = 2 ; // Unable to answer.
2017-09-05 09:41:48 +02:00
else if ( ability = = gAIScriptPtr [ 2 ] )
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = 1 ; // Pokemon has the ability we wanted to check.
2017-02-04 03:34:56 +01:00
else
2018-06-17 16:48:58 +02:00
AI_THINKING_STRUCT - > funcResult = 0 ; // Pokemon doesn't have the ability we wanted to check.
2017-02-04 03:34:56 +01:00
gAIScriptPtr + = 3 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_32 ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_33 ( void )
2017-02-04 03:34:56 +01:00
{
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 )
{
2020-12-13 05:28:01 +01:00
gAIScriptPtr + = 10 ;
2020-12-13 05:57:25 +01:00
# ifdef UBFIX
2020-12-13 05:28:01 +01:00
return ;
# endif
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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_is_double_battle ( void )
2017-02-04 03:34:56 +01:00
{
AI_THINKING_STRUCT - > funcResult = gBattleTypeFlags & BATTLE_TYPE_DOUBLE ;
gAIScriptPtr + = 1 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_52 ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_53 ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_54 ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_55 ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_56 ( void )
2017-02-04 03:34:56 +01:00
{
}
2021-01-23 05:22:37 +01:00
static void Cmd_nop_57 ( void )
2017-02-04 03:34:56 +01:00
{
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
}
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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 ;
}
2019-08-23 14:10:37 +02:00
static void Cmd_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
2019-04-04 23:53:06 +02:00
if ( gBattleResources - > flags - > flags [ battlerId ] & RESOURCE_FLAG_FLASH_FIRE )
2018-03-01 00:59:52 +01:00
gAIScriptPtr = T1_READ_PTR ( gAIScriptPtr + 2 ) ;
2017-02-04 03:34:56 +01:00
else
gAIScriptPtr + = 6 ;
}
2017-09-17 14:10:32 +02:00
static void AIStackPushVar ( const u8 * var )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
gBattleResources - > AI_ScriptsStack - > ptr [ gBattleResources - > AI_ScriptsStack - > size + + ] = var ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static void AIStackPushVar_cursor ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
gBattleResources - > AI_ScriptsStack - > ptr [ gBattleResources - > AI_ScriptsStack - > size + + ] = gAIScriptPtr ;
2017-02-04 03:34:56 +01:00
}
2017-09-05 09:41:48 +02:00
static bool8 AIStackPop ( void )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
if ( gBattleResources - > AI_ScriptsStack - > size ! = 0 )
2017-02-04 03:34:56 +01:00
{
2017-09-04 21:43:13 +02:00
- - gBattleResources - > AI_ScriptsStack - > size ;
gAIScriptPtr = gBattleResources - > AI_ScriptsStack - > ptr [ gBattleResources - > AI_ScriptsStack - > size ] ;
2017-02-04 03:34:56 +01:00
return TRUE ;
}
else
2018-06-17 16:48:58 +02:00
{
2017-02-04 03:34:56 +01:00
return FALSE ;
2018-06-17 16:48:58 +02:00
}
2017-02-04 03:34:56 +01:00
}