mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 11:44:17 +01:00
more ai stuff, baton pass perish song strats
This commit is contained in:
parent
7647941ec4
commit
a41ecf7101
@ -640,6 +640,30 @@
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro if_battler_absent battler:req, ptr:req
|
||||
.byte 0x70
|
||||
.byte \battler
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro if_grounded battler:req, ptr:req
|
||||
.byte 0x71
|
||||
.byte \battler
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro get_best_dmg_hp_percent
|
||||
.byte 0x72
|
||||
.endm
|
||||
|
||||
.macro get_curr_dmg_hp_percent
|
||||
.byte 0x73
|
||||
.endm
|
||||
|
||||
.macro get_move_split_from_result
|
||||
.byte 0x74
|
||||
.endm
|
||||
|
||||
@ useful script macros
|
||||
.macro if_has_physical_move battler:req, ptr:req
|
||||
if_has_move_with_split \battler, SPLIT_PHYSICAL, \ptr
|
||||
|
@ -163,6 +163,7 @@ AI_CheckBadMove_CheckEffect: @ 82DC045
|
||||
if_effect EFFECT_SANDSTORM, AI_CBM_Sandstorm
|
||||
if_effect EFFECT_SWAGGER, AI_CBM_Confuse
|
||||
if_effect EFFECT_ATTRACT, AI_CBM_Attract
|
||||
if_effect EFFECT_CAPTIVATE, AI_CBM_Captivate
|
||||
if_effect EFFECT_RETURN, AI_CBM_HighRiskForDamage
|
||||
if_effect EFFECT_PRESENT, AI_CBM_HighRiskForDamage
|
||||
if_effect EFFECT_FRUSTRATION, AI_CBM_HighRiskForDamage
|
||||
@ -254,6 +255,12 @@ AI_CheckBadMove_CheckEffect: @ 82DC045
|
||||
if_effect EFFECT_PROTECT, AI_CBM_Protect
|
||||
if_effect EFFECT_TAUNT, AI_CBM_Taunt
|
||||
if_effect EFFECT_HEAL_BELL, AI_CBM_HealBell
|
||||
if_effect EFFECT_FOLLOW_ME, AI_CBM_FollowMe
|
||||
end
|
||||
|
||||
AI_CBM_FollowMe:
|
||||
if_not_double_battle Score_Minus10
|
||||
if_battler_absent AI_USER_PARTNER, Score_Minus10
|
||||
end
|
||||
|
||||
AI_CBM_HealBell:
|
||||
@ -724,26 +731,33 @@ AI_CBM_Sandstorm: @ 82DC5ED
|
||||
get_weather
|
||||
if_equal AI_WEATHER_SANDSTORM, Score_Minus8
|
||||
end
|
||||
|
||||
AI_CBM_Attract: @ 82DC5F5
|
||||
if_status2 AI_TARGET, STATUS2_INFATUATION, Score_Minus10
|
||||
|
||||
AI_IsOppositeGender:
|
||||
get_ability AI_TARGET
|
||||
if_equal ABILITY_OBLIVIOUS, Score_Minus10
|
||||
get_gender AI_USER
|
||||
if_equal 0, AI_CBM_Attract_CheckIfTargetIsFemale
|
||||
if_equal 254, AI_CBM_Attract_CheckIfTargetIsMale
|
||||
if_equal 0, AI_IsOppositeGenderFemale
|
||||
if_equal 254, AI_IsOppositeGenderMale
|
||||
goto Score_Minus10
|
||||
|
||||
AI_CBM_Attract_CheckIfTargetIsFemale: @ 82DC61A
|
||||
AI_IsOppositeGenderFemale: @ 82DC61A
|
||||
get_gender AI_TARGET
|
||||
if_equal 254, AI_CBM_Attract_End
|
||||
goto Score_Minus10
|
||||
|
||||
AI_CBM_Attract_CheckIfTargetIsMale: @ 82DC627
|
||||
AI_IsOppositeGenderMale: @ 82DC627
|
||||
get_gender AI_TARGET
|
||||
if_equal 0, AI_CBM_Attract_End
|
||||
goto Score_Minus10
|
||||
end
|
||||
|
||||
AI_CBM_Captivate:
|
||||
call AI_IsOppositeGender
|
||||
goto AI_CBM_SpAtkDown
|
||||
|
||||
AI_CBM_Attract: @ 82DC5F5
|
||||
if_status2 AI_TARGET, STATUS2_INFATUATION, Score_Minus10
|
||||
call AI_IsOppositeGender
|
||||
end
|
||||
|
||||
AI_CBM_Attract_End: @ 82DC634
|
||||
end
|
||||
|
||||
@ -942,6 +956,19 @@ AI_CV_DmgMove:
|
||||
get_how_powerful_move_is
|
||||
if_equal MOVE_POWER_WEAK, Score_Minus1
|
||||
end
|
||||
|
||||
@ If move deals shit damage, and there are other mons to switch in, use support moves instead
|
||||
AI_WeakDmg:
|
||||
get_considered_move_power
|
||||
if_equal 0, AI_Ret
|
||||
if_has_no_move_with_split AI_USER, SPLIT_STATUS, AI_Ret
|
||||
get_curr_dmg_hp_percent
|
||||
if_more_than 30, AI_Ret
|
||||
if_more_than 20, Score_Minus1
|
||||
get_how_powerful_move_is
|
||||
if_equal MOVE_POWER_BEST, Score_Minus2
|
||||
score -3
|
||||
end
|
||||
|
||||
AI_CheckViability:
|
||||
if_target_is_ally AI_Ret
|
||||
@ -949,6 +976,7 @@ AI_CheckViability:
|
||||
call_if_move_flag FLAG_HIGH_CRIT, AI_CV_HighCrit
|
||||
call AI_CheckIfAlreadyDead
|
||||
call AI_CV_DmgMove
|
||||
call AI_WeakDmg
|
||||
if_effect EFFECT_HIT, AI_CV_Hit
|
||||
if_effect EFFECT_SLEEP, AI_CV_Sleep
|
||||
if_effect EFFECT_ABSORB, AI_CV_Absorb
|
||||
@ -1081,8 +1109,31 @@ AI_CheckViability:
|
||||
if_effect EFFECT_SPIKES, AI_CV_Hazards
|
||||
if_effect EFFECT_STICKY_WEB, AI_CV_Hazards
|
||||
if_effect EFFECT_TOXIC_SPIKES, AI_CV_Hazards
|
||||
if_effect EFFECT_PERISH_SONG, AI_CV_PerishSong
|
||||
end
|
||||
|
||||
AI_CV_PerishSong:
|
||||
get_ability AI_USER
|
||||
if_equal ABILITY_ARENA_TRAP, AI_CV_PerishSong_ArenaTrap
|
||||
if_equal ABILITY_MAGNET_PULL, AI_CV_PerishSong_MagnetPull
|
||||
if_equal ABILITY_SHADOW_TAG, AI_CV_PerishSong_ShadowTag
|
||||
AI_CV_PerishSongCheckTrap:
|
||||
if_status2 AI_TARGET, STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION, Score_Plus3
|
||||
@ If has a move that can trap, use it first, then use Perish Song
|
||||
if_double_battle AI_Ret
|
||||
if_has_move_with_effect AI_USER, EFFECT_TRAP, Score_Minus5
|
||||
if_has_move_with_effect AI_USER, EFFECT_MEAN_LOOK, Score_Minus5
|
||||
end
|
||||
AI_CV_PerishSong_ArenaTrap:
|
||||
if_grounded AI_TARGET, Score_Plus2
|
||||
goto AI_CV_PerishSongCheckTrap
|
||||
AI_CV_PerishSong_MagnetPull:
|
||||
if_type AI_TARGET, TYPE_STEEL, Score_Plus2
|
||||
goto AI_CV_PerishSongCheckTrap
|
||||
AI_CV_PerishSong_ShadowTag:
|
||||
if_no_ability AI_TARGET, ABILITY_SHADOW_TAG, Score_Plus2
|
||||
goto AI_CV_PerishSongCheckTrap
|
||||
|
||||
AI_CV_Hazards:
|
||||
if_ability AI_TARGET, ABILITY_MAGIC_BOUNCE, AI_CV_StealthRockEnd
|
||||
is_first_turn_for AI_USER
|
||||
@ -1315,8 +1366,8 @@ AI_CV_DefenseUp4: @ 82DCC28
|
||||
get_move_power_from_result
|
||||
if_equal 0, AI_CV_DefenseUp5
|
||||
get_last_used_bank_move AI_TARGET
|
||||
get_move_type_from_result
|
||||
if_not_in_bytes AI_CV_DefenseUp_PhysicalTypes, AI_CV_DefenseUp_ScoreDown2
|
||||
get_move_split_from_result
|
||||
if_not_equal SPLIT_PHYSICAL, AI_CV_DefenseUp_ScoreDown2
|
||||
if_random_less_than 60, AI_CV_DefenseUp_End
|
||||
|
||||
AI_CV_DefenseUp5: @ 82DCC4A
|
||||
@ -1328,18 +1379,6 @@ AI_CV_DefenseUp_ScoreDown2: @ 82DCC50
|
||||
AI_CV_DefenseUp_End: @ 82DCC52
|
||||
end
|
||||
|
||||
AI_CV_DefenseUp_PhysicalTypes: @ 82DCC53
|
||||
.byte TYPE_NORMAL
|
||||
.byte TYPE_FIGHTING
|
||||
.byte TYPE_POISON
|
||||
.byte TYPE_GROUND
|
||||
.byte TYPE_FLYING
|
||||
.byte TYPE_ROCK
|
||||
.byte TYPE_BUG
|
||||
.byte TYPE_GHOST
|
||||
.byte TYPE_STEEL
|
||||
.byte -1
|
||||
|
||||
AI_CV_SpeedUp: @ 82DCC5D
|
||||
if_target_faster AI_CV_SpeedUp2
|
||||
score -3
|
||||
@ -1395,8 +1434,8 @@ AI_CV_SpDefUp4: @ 82DCCDF
|
||||
get_move_power_from_result
|
||||
if_equal 0, AI_CV_SpDefUp5
|
||||
get_last_used_bank_move AI_TARGET
|
||||
get_move_type_from_result
|
||||
if_in_bytes AI_CV_SpDefUp_PhysicalTypes, AI_CV_SpDefUp_ScoreDown2
|
||||
get_move_split_from_result
|
||||
if_not_equal SPLIT_SPECIAL, AI_CV_SpDefUp_ScoreDown2
|
||||
if_random_less_than 60, AI_CV_SpDefUp_End
|
||||
|
||||
AI_CV_SpDefUp5: @ 82DCD01
|
||||
@ -1408,18 +1447,6 @@ AI_CV_SpDefUp_ScoreDown2: @ 82DCD07
|
||||
AI_CV_SpDefUp_End: @ 82DCD09
|
||||
end
|
||||
|
||||
AI_CV_SpDefUp_PhysicalTypes: @ 82DCD0A
|
||||
.byte TYPE_NORMAL
|
||||
.byte TYPE_FIGHTING
|
||||
.byte TYPE_POISON
|
||||
.byte TYPE_GROUND
|
||||
.byte TYPE_FLYING
|
||||
.byte TYPE_ROCK
|
||||
.byte TYPE_BUG
|
||||
.byte TYPE_GHOST
|
||||
.byte TYPE_STEEL
|
||||
.byte -1
|
||||
|
||||
AI_CV_AccuracyUp:
|
||||
if_stat_level_less_than AI_USER, STAT_ACC, 9, AI_CV_AccuracyUp2
|
||||
if_random_less_than 50, AI_CV_AccuracyUp2
|
||||
@ -1895,11 +1922,15 @@ AI_CV_SuperFang:
|
||||
|
||||
AI_CV_SuperFang_End:
|
||||
end
|
||||
|
||||
|
||||
AI_CV_Trap:
|
||||
if_status2 AI_TARGET, STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION, AI_CV_TrapEnd
|
||||
if_status3 AI_TARGET, STATUS3_PERISH_SONG, AI_CV_Trap5
|
||||
if_doesnt_have_move_with_effect AI_USER, EFFECT_PERISH_SONG, AI_CV_Trap1
|
||||
score +3
|
||||
AI_CV_Trap1:
|
||||
if_status AI_TARGET, STATUS1_TOXIC_POISON, AI_CV_Trap2
|
||||
if_status2 AI_TARGET, STATUS2_CURSED | STATUS2_INFATUATION, AI_CV_Trap2
|
||||
if_status3 AI_TARGET, STATUS3_PERISH_SONG, AI_CV_Trap5
|
||||
goto AI_CV_TrapItem
|
||||
AI_CV_Trap5:
|
||||
score +2
|
||||
@ -2069,20 +2100,27 @@ AI_CV_VitalThrow_End:
|
||||
end
|
||||
|
||||
AI_CV_Substitute:
|
||||
if_not_status2 AI_TARGET, STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION, AI_CV_Substitute1
|
||||
if_status3 AI_TARGET, STATUS3_PERISH_SONG, AI_CV_SubstitutePlus3Continue
|
||||
if_status AI_TARGET, STATUS1_BURN | STATUS1_PSN_ANY, AI_CV_SubstitutePlus1Continue
|
||||
goto AI_CV_Substitute1
|
||||
AI_CV_SubstitutePlus1Continue:
|
||||
score +1
|
||||
goto AI_CV_Substitute1
|
||||
AI_CV_SubstitutePlus3Continue:
|
||||
score +3
|
||||
AI_CV_Substitute1:
|
||||
if_hp_more_than AI_USER, 90, AI_CV_Substitute4
|
||||
if_hp_more_than AI_USER, 70, AI_CV_Substitute3
|
||||
if_hp_more_than AI_USER, 50, AI_CV_Substitute2
|
||||
if_random_less_than 100, AI_CV_Substitute2
|
||||
score -1
|
||||
|
||||
AI_CV_Substitute2:
|
||||
if_random_less_than 100, AI_CV_Substitute3
|
||||
score -1
|
||||
|
||||
AI_CV_Substitute3:
|
||||
if_random_less_than 100, AI_CV_Substitute4
|
||||
score -1
|
||||
|
||||
AI_CV_Substitute4:
|
||||
if_target_faster AI_CV_Substitute_End
|
||||
get_last_used_bank_move AI_TARGET
|
||||
@ -2095,22 +2133,17 @@ AI_CV_Substitute4:
|
||||
if_equal EFFECT_CONFUSE, AI_CV_Substitute6
|
||||
if_equal EFFECT_LEECH_SEED, AI_CV_Substitute7
|
||||
goto AI_CV_Substitute_End
|
||||
|
||||
AI_CV_Substitute5:
|
||||
if_not_status AI_TARGET, STATUS1_ANY, AI_CV_Substitute8
|
||||
goto AI_CV_Substitute_End
|
||||
|
||||
AI_CV_Substitute6:
|
||||
if_not_status2 AI_TARGET, STATUS2_CONFUSION, AI_CV_Substitute8
|
||||
goto AI_CV_Substitute_End
|
||||
|
||||
AI_CV_Substitute7:
|
||||
if_status3 AI_TARGET, STATUS3_LEECHSEED, AI_CV_Substitute_End
|
||||
|
||||
AI_CV_Substitute8:
|
||||
if_random_less_than 100, AI_CV_Substitute_End
|
||||
score +1
|
||||
|
||||
AI_CV_Substitute_End:
|
||||
end
|
||||
|
||||
@ -2525,20 +2558,16 @@ AI_CV_BatonPass:
|
||||
if_stat_level_more_than AI_USER, STAT_SPDEF, 8, AI_CV_BatonPass2
|
||||
if_stat_level_more_than AI_USER, STAT_EVASION, 8, AI_CV_BatonPass2
|
||||
goto AI_CV_BatonPass5
|
||||
|
||||
AI_CV_BatonPass2:
|
||||
if_target_faster AI_CV_BatonPass3
|
||||
if_hp_more_than AI_USER, 60, AI_CV_BatonPass_End
|
||||
if_hp_more_than AI_USER, 60, AI_CV_BatonPass_Last
|
||||
goto AI_CV_BatonPass4
|
||||
|
||||
AI_CV_BatonPass3:
|
||||
if_hp_more_than AI_USER, 70, AI_CV_BatonPass_End
|
||||
|
||||
if_hp_more_than AI_USER, 70, AI_CV_BatonPass_Last
|
||||
AI_CV_BatonPass4:
|
||||
if_random_less_than 80, AI_CV_BatonPass_End
|
||||
if_random_less_than 80, AI_CV_BatonPass_Last
|
||||
score +2
|
||||
goto AI_CV_BatonPass_End
|
||||
|
||||
goto AI_CV_BatonPass_Last
|
||||
AI_CV_BatonPass5:
|
||||
if_stat_level_more_than AI_USER, STAT_ATK, 7, AI_CV_BatonPass7
|
||||
if_stat_level_more_than AI_USER, STAT_DEF, 7, AI_CV_BatonPass7
|
||||
@ -2546,18 +2575,38 @@ AI_CV_BatonPass5:
|
||||
if_stat_level_more_than AI_USER, STAT_SPDEF, 7, AI_CV_BatonPass7
|
||||
if_stat_level_more_than AI_USER, STAT_EVASION, 7, AI_CV_BatonPass7
|
||||
goto AI_CV_BatonPass_ScoreDown2
|
||||
|
||||
AI_CV_BatonPass7:
|
||||
if_target_faster AI_CV_BatonPass8
|
||||
if_ai_can_go_down AI_CV_BatonPass4
|
||||
if_hp_more_than AI_USER, 60, AI_CV_BatonPass_ScoreDown2
|
||||
goto AI_CV_BatonPass_End
|
||||
|
||||
goto AI_CV_BatonPass_Last
|
||||
AI_CV_BatonPass8:
|
||||
if_hp_less_than AI_USER, 70, AI_CV_BatonPass_End
|
||||
|
||||
if_ai_can_go_down AI_CV_BatonPass_ScoreDown2
|
||||
if_hp_less_than AI_USER, 70, AI_CV_BatonPass_Last
|
||||
goto AI_CV_BatonPass_ScoreDown2
|
||||
AI_CV_BatonPass9:
|
||||
if_stat_level_more_than AI_USER, STAT_ATK, 6, AI_CV_BatonPass10
|
||||
if_stat_level_more_than AI_USER, STAT_DEF, 6, AI_CV_BatonPass10
|
||||
if_stat_level_more_than AI_USER, STAT_SPATK, 6, AI_CV_BatonPass10
|
||||
if_stat_level_more_than AI_USER, STAT_SPDEF, 6, AI_CV_BatonPass10
|
||||
if_stat_level_more_than AI_USER, STAT_EVASION, 6, AI_CV_BatonPass10
|
||||
goto AI_CV_BatonPass_ScoreDown2
|
||||
AI_CV_BatonPass10:
|
||||
if_target_faster AI_CV_BatonPass11
|
||||
if_ai_can_go_down AI_CV_BatonPass4
|
||||
if_hp_more_than AI_USER, 60, AI_CV_BatonPass_ScoreDown2
|
||||
goto AI_CV_BatonPass_Last
|
||||
AI_CV_BatonPass11:
|
||||
if_ai_can_go_down AI_CV_BatonPass_ScoreDown2
|
||||
if_hp_less_than AI_USER, 70, AI_CV_BatonPass_Last
|
||||
goto AI_CV_BatonPass_ScoreDown2
|
||||
AI_CV_BatonPass_ScoreDown2:
|
||||
score -2
|
||||
|
||||
end
|
||||
AI_CV_BatonPass_Last:
|
||||
get_best_dmg_hp_percent
|
||||
if_less_than 10, Score_Plus2
|
||||
if_less_than 20, Score_Plus1
|
||||
AI_CV_BatonPass_End:
|
||||
end
|
||||
|
||||
@ -3386,36 +3435,7 @@ AI_Risky_EffectsToEncourage:
|
||||
.byte EFFECT_REVENGE
|
||||
.byte EFFECT_TEETER_DANCE
|
||||
.byte -1
|
||||
|
||||
AI_PreferBatonPass:
|
||||
if_target_is_ally AI_Ret
|
||||
count_usable_party_mons AI_USER
|
||||
if_equal 0, AI_PreferBatonPassEnd
|
||||
get_how_powerful_move_is
|
||||
if_not_equal MOVE_POWER_DISCOURAGED, AI_PreferBatonPassEnd
|
||||
if_has_move_with_effect AI_USER, EFFECT_BATON_PASS, AI_PreferBatonPass_GoForBatonPass
|
||||
if_random_less_than 80, AI_Risky_End
|
||||
|
||||
AI_PreferBatonPass_GoForBatonPass:
|
||||
get_considered_move_effect
|
||||
if_in_hwords sEffectsStatRaise, AI_PreferBatonPass2
|
||||
if_effect EFFECT_PROTECT, AI_PreferBatonPass_End
|
||||
if_move MOVE_BATON_PASS, AI_PreferBatonPass_EncourageIfHighStats
|
||||
if_random_less_than 20, AI_Risky_End
|
||||
score +3
|
||||
|
||||
AI_PreferBatonPass2:
|
||||
get_turn_count
|
||||
if_equal 0, Score_Plus5
|
||||
if_hp_less_than AI_USER, 60, Score_Minus10
|
||||
goto Score_Plus1
|
||||
|
||||
AI_PreferBatonPass_End:
|
||||
get_last_used_bank_move AI_USER
|
||||
if_in_hwords sMovesTable_ProtectMoves, Score_Minus2
|
||||
score +2
|
||||
end
|
||||
|
||||
|
||||
.align 1
|
||||
sMovesTable_ProtectMoves:
|
||||
.2byte MOVE_PROTECT
|
||||
@ -3423,10 +3443,15 @@ sMovesTable_ProtectMoves:
|
||||
.2byte -1
|
||||
|
||||
sEffectsStatRaise:
|
||||
.2byte EFFECT_ATTACK_UP
|
||||
.2byte EFFECT_ATTACK_UP_2
|
||||
.2byte EFFECT_DEFENSE_UP
|
||||
.2byte EFFECT_DEFENSE_UP_2
|
||||
.2byte EFFECT_SPEED_UP
|
||||
.2byte EFFECT_SPEED_UP_2
|
||||
.2byte EFFECT_SPECIAL_ATTACK_UP
|
||||
.2byte EFFECT_SPECIAL_ATTACK_UP_2
|
||||
.2byte EFFECT_SPECIAL_DEFENSE_UP
|
||||
.2byte EFFECT_SPECIAL_DEFENSE_UP_2
|
||||
.2byte EFFECT_CALM_MIND
|
||||
.2byte EFFECT_DRAGON_DANCE
|
||||
@ -3440,6 +3465,28 @@ sEffectsStatRaise:
|
||||
.2byte EFFECT_QUIVER_DANCE
|
||||
.2byte -1
|
||||
|
||||
AI_PreferBatonPass:
|
||||
if_target_is_ally AI_Ret
|
||||
count_usable_party_mons AI_USER
|
||||
if_equal 0, AI_PreferBatonPassEnd
|
||||
get_how_powerful_move_is
|
||||
if_not_equal MOVE_POWER_DISCOURAGED, AI_PreferBatonPassEnd
|
||||
if_doesnt_have_move_with_effect AI_USER, EFFECT_BATON_PASS, AI_PreferBatonPassEnd
|
||||
get_considered_move_effect
|
||||
if_in_hwords sEffectsStatRaise, AI_PreferBatonPass2
|
||||
if_effect EFFECT_PROTECT, AI_PreferBatonPass3
|
||||
if_move MOVE_BATON_PASS, AI_PreferBatonPass_EncourageIfHighStats
|
||||
end
|
||||
AI_PreferBatonPass2:
|
||||
get_turn_count
|
||||
if_equal 0, Score_Plus5
|
||||
if_hp_less_than AI_USER, 60, Score_Minus10
|
||||
goto Score_Plus1
|
||||
AI_PreferBatonPass3:
|
||||
get_last_used_bank_move AI_USER
|
||||
if_in_hwords sMovesTable_ProtectMoves, Score_Minus2
|
||||
score +2
|
||||
end
|
||||
AI_PreferBatonPass_EncourageIfHighStats:
|
||||
get_turn_count
|
||||
if_equal 0, Score_Minus2
|
||||
@ -3450,7 +3497,6 @@ AI_PreferBatonPass_EncourageIfHighStats:
|
||||
if_stat_level_more_than AI_USER, STAT_SPATK, 7, Score_Plus2
|
||||
if_stat_level_more_than AI_USER, STAT_SPATK, 6, Score_Plus1
|
||||
end
|
||||
|
||||
AI_PreferBatonPassEnd:
|
||||
end
|
||||
|
||||
@ -3459,6 +3505,7 @@ AI_ConsiderAllyChosenMove:
|
||||
if_equal 0, AI_ConsiderAllyChosenMoveRet
|
||||
get_move_effect_from_result
|
||||
if_equal EFFECT_HELPING_HAND, AI_PartnerChoseHelpingHand
|
||||
if_equal EFFECT_PERISH_SONG, AI_PartnerChosePerishSong
|
||||
AI_ConsiderAllyChosenMoveRet:
|
||||
end
|
||||
|
||||
@ -3468,17 +3515,30 @@ AI_PartnerChoseHelpingHand:
|
||||
if_equal 0, Score_Minus5
|
||||
end
|
||||
|
||||
AI_PartnerChosePerishSong:
|
||||
if_status2 AI_TARGET, STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED, AI_Ret
|
||||
get_considered_move_effect
|
||||
if_equal EFFECT_MEAN_LOOK, Score_Plus1
|
||||
if_equal EFFECT_TRAP, Score_Plus1
|
||||
end
|
||||
|
||||
AI_ConsiderAllyKnownMoves:
|
||||
@ If ally already chose a move, there is nothing to do here.
|
||||
get_ally_chosen_move
|
||||
if_not_equal 0, AI_Ret
|
||||
if_move MOVE_HELPING_HAND, AI_HelpingHandInDoubles
|
||||
if_move MOVE_PERISH_SONG, AI_PerishSongInDoubles
|
||||
end
|
||||
|
||||
AI_HelpingHandInDoubles:
|
||||
if_has_no_attacking_moves AI_USER_PARTNER, Score_Minus5
|
||||
end
|
||||
|
||||
AI_PerishSongInDoubles:
|
||||
if_has_move_with_effect AI_USER_PARTNER, EFFECT_MEAN_LOOK, Score_Plus1
|
||||
if_has_move_with_effect AI_USER_PARTNER, EFFECT_TRAP, Score_Plus1
|
||||
end
|
||||
|
||||
AI_DoubleBattle:
|
||||
call AI_ConsiderAllyChosenMove
|
||||
call AI_ConsiderAllyKnownMoves
|
||||
|
@ -170,6 +170,11 @@ static void BattleAICmd_if_ai_can_go_down(void);
|
||||
static void BattleAICmd_if_has_move_with_type(void);
|
||||
static void BattleAICmd_if_no_move_used(void);
|
||||
static void BattleAICmd_if_has_move_with_flag(void);
|
||||
static void BattleAICmd_if_battler_absent(void);
|
||||
static void BattleAICmd_is_grounded(void);
|
||||
static void BattleAICmd_get_best_dmg_hp_percent(void);
|
||||
static void BattleAICmd_get_curr_dmg_hp_percent(void);
|
||||
static void BattleAICmd_get_move_split_from_result(void);
|
||||
|
||||
// ewram
|
||||
EWRAM_DATA const u8 *gAIScriptPtr = NULL;
|
||||
@ -292,6 +297,11 @@ static const BattleAICmdFunc sBattleAICmdTable[] =
|
||||
BattleAICmd_if_has_move_with_type, // 0x6D
|
||||
BattleAICmd_if_no_move_used, // 0x6E
|
||||
BattleAICmd_if_has_move_with_flag, // 0x6F
|
||||
BattleAICmd_if_battler_absent, // 0x70
|
||||
BattleAICmd_is_grounded, // 0x71
|
||||
BattleAICmd_get_best_dmg_hp_percent, // 0x72
|
||||
BattleAICmd_get_curr_dmg_hp_percent, // 0x73
|
||||
BattleAICmd_get_move_split_from_result, // 0x74
|
||||
};
|
||||
|
||||
static const u16 sDiscouragedPowerfulMoveEffects[] =
|
||||
@ -404,7 +414,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves)
|
||||
move = gBattleMons[sBattler_AI].moves[i];
|
||||
if (gBattleMoves[move].power != 0 && !(moveLimitations & gBitTable[i]))
|
||||
{
|
||||
dmg = AI_CalcDamage(move, sBattler_AI, gBattlerTarget) * (100 - (Random() % 16)) / 100;
|
||||
dmg = AI_CalcDamage(move, sBattler_AI, gBattlerTarget) * (100 - (Random() % 10)) / 100;
|
||||
if (dmg == 0)
|
||||
dmg = 1;
|
||||
}
|
||||
@ -2665,3 +2675,53 @@ static void BattleAICmd_if_no_move_used(void)
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleAICmd_if_battler_absent(void)
|
||||
{
|
||||
u32 battler = BattleAI_GetWantedBattler(gAIScriptPtr[1]);
|
||||
|
||||
if (!IsBattlerAlive(battler))
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
|
||||
else
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
|
||||
static void BattleAICmd_is_grounded(void)
|
||||
{
|
||||
u32 battler = BattleAI_GetWantedBattler(gAIScriptPtr[1]);
|
||||
|
||||
if (IsBattlerGrounded(battler))
|
||||
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
|
||||
else
|
||||
gAIScriptPtr += 6;
|
||||
}
|
||||
|
||||
static void BattleAICmd_get_best_dmg_hp_percent(void)
|
||||
{
|
||||
int i, bestDmg;
|
||||
|
||||
bestDmg = 0;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (gBattleResources->ai->simulatedDmg[sBattler_AI][gBattlerTarget][i] > bestDmg)
|
||||
bestDmg = gBattleResources->ai->simulatedDmg[sBattler_AI][gBattlerTarget][i];
|
||||
}
|
||||
|
||||
gBattleResources->ai->funcResult = (bestDmg * 100) / gBattleMons[gBattlerTarget].maxHP;
|
||||
gAIScriptPtr++;
|
||||
}
|
||||
|
||||
static void BattleAICmd_get_curr_dmg_hp_percent(void)
|
||||
{
|
||||
int bestDmg = gBattleResources->ai->simulatedDmg[sBattler_AI][gBattlerTarget][AI_THINKING_STRUCT->movesetIndex];
|
||||
|
||||
gBattleResources->ai->funcResult = (bestDmg * 100) / gBattleMons[gBattlerTarget].maxHP;
|
||||
gAIScriptPtr++;
|
||||
}
|
||||
|
||||
static void BattleAICmd_get_move_split_from_result(void)
|
||||
{
|
||||
AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].type;
|
||||
|
||||
gAIScriptPtr += 1;
|
||||
}
|
||||
|
@ -579,15 +579,15 @@ void AI_TrySwitchOrUseItem(void)
|
||||
|
||||
u8 GetMostSuitableMonToSwitchInto(void)
|
||||
{
|
||||
u8 opposingBattler;
|
||||
u32 bestDmg;
|
||||
u8 bestMonId;
|
||||
u8 battlerIn1, battlerIn2;
|
||||
s32 firstId;
|
||||
s32 lastId; // + 1
|
||||
u8 opposingBattler = 0;
|
||||
u32 bestDmg = 0;
|
||||
u8 bestMonId = 0;
|
||||
u8 battlerIn1 = 0, battlerIn2 = 0;
|
||||
s32 firstId = 0;
|
||||
s32 lastId = 0; // + 1
|
||||
struct Pokemon *party;
|
||||
s32 i, j;
|
||||
u8 invalidMons;
|
||||
s32 i, j, aliveCount = 0;
|
||||
u8 invalidMons = 0, bits = 0;
|
||||
u16 move;
|
||||
|
||||
if (*(gBattleStruct->monToSwitchIntoId + gActiveBattler) != PARTY_SIZE)
|
||||
@ -603,8 +603,7 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
else
|
||||
battlerIn2 = GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK);
|
||||
|
||||
// UB: It considers the opponent only player's side even though it can battle alongside player.
|
||||
opposingBattler = Random() & BIT_FLANK;
|
||||
opposingBattler = BATTLE_OPPOSITE(battlerIn1);
|
||||
if (gAbsentBattlerFlags & gBitTable[opposingBattler])
|
||||
opposingBattler ^= BIT_FLANK;
|
||||
}
|
||||
@ -622,24 +621,56 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
invalidMons = 0;
|
||||
// Get invalid slots ids.
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE
|
||||
|| GetMonData(&party[i], MON_DATA_HP) == 0
|
||||
|| gBattlerPartyIndexes[battlerIn1] == i
|
||||
|| gBattlerPartyIndexes[battlerIn2] == i
|
||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn1)
|
||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
invalidMons |= gBitTable[i];
|
||||
else
|
||||
aliveCount++;
|
||||
}
|
||||
|
||||
while (invalidMons != 0x3F) // All mons are invalid.
|
||||
// If there are two(or more) mons to choose from, always choose one that has baton pass
|
||||
// as most often it can't do much on its own.
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
if (invalidMons & gBitTable[i])
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; j++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL) == MOVE_BATON_PASS)
|
||||
{
|
||||
bits |= gBitTable[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((aliveCount == 2 || (aliveCount > 2 && Random() % 3 == 0)) && bits)
|
||||
{
|
||||
do
|
||||
{
|
||||
bestMonId = (Random() % (lastId - firstId)) + firstId;
|
||||
} while (!(bits & gBitTable[bestMonId]));
|
||||
return bestMonId;
|
||||
}
|
||||
|
||||
bits = 0;
|
||||
while (bits != 0x3F) // All mons are invalid.
|
||||
{
|
||||
bestDmg = 0;
|
||||
bestMonId = 6;
|
||||
bestMonId = PARTY_SIZE;
|
||||
// Find the mon whose type is the most suitable offensively.
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
u16 species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||
if (species != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& !(gBitTable[i] & invalidMons)
|
||||
&& gBattlerPartyIndexes[battlerIn1] != i
|
||||
&& gBattlerPartyIndexes[battlerIn2] != i
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + battlerIn1)
|
||||
&& i != *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
if (!(gBitTable[i] & invalidMons) && !(gBitTable[i] & bits))
|
||||
{
|
||||
u16 species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||
u32 typeDmg = UQ_4_12(1.0);
|
||||
|
||||
u8 atkType1 = gBaseStats[species].type1;
|
||||
@ -662,10 +693,6 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
bestMonId = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
invalidMons |= gBitTable[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, we know the mon has the right typing but does it have at least one super effective move?
|
||||
@ -681,11 +708,11 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
if (i != MAX_MON_MOVES)
|
||||
return bestMonId; // Has both the typing and at least one super effective move.
|
||||
|
||||
invalidMons |= gBitTable[bestMonId]; // Sorry buddy, we want something better.
|
||||
bits |= gBitTable[bestMonId]; // Sorry buddy, we want something better.
|
||||
}
|
||||
else
|
||||
{
|
||||
invalidMons = 0x3F; // No viable mon to switch.
|
||||
bits = 0x3F; // No viable mon to switch.
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,31 +724,20 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
||||
// If we couldn't find the best mon in terms of typing, find the one that deals most damage.
|
||||
for (i = firstId; i < lastId; i++)
|
||||
{
|
||||
if ((u16)(GetMonData(&party[i], MON_DATA_SPECIES)) == SPECIES_NONE)
|
||||
continue;
|
||||
if (GetMonData(&party[i], MON_DATA_HP) == 0)
|
||||
continue;
|
||||
if (gBattlerPartyIndexes[battlerIn1] == i)
|
||||
continue;
|
||||
if (gBattlerPartyIndexes[battlerIn2] == i)
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|
||||
continue;
|
||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
if (gBitTable[i] & invalidMons)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; j++)
|
||||
{
|
||||
s32 dmg = 0;
|
||||
move = GetMonData(&party[i], MON_DATA_MOVE1 + j);
|
||||
if (move != MOVE_NONE && gBattleMoves[move].power != 1)
|
||||
if (move != MOVE_NONE && gBattleMoves[move].power != 0)
|
||||
{
|
||||
dmg = AI_CalcPartyMonDamage(move, gActiveBattler, opposingBattler, &party[i]);
|
||||
}
|
||||
if (bestDmg < dmg)
|
||||
{
|
||||
bestDmg = dmg;
|
||||
bestMonId = i;
|
||||
s32 dmg = AI_CalcPartyMonDamage(move, gActiveBattler, opposingBattler, &party[i]);
|
||||
if (bestDmg < dmg)
|
||||
{
|
||||
bestDmg = dmg;
|
||||
bestMonId = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user