diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_4.c | 595 | ||||
-rw-r--r-- | src/battle_ai.c | 1384 | ||||
-rw-r--r-- | src/calculate_base_damage.c | 284 | ||||
-rw-r--r-- | src/load_save.c | 114 | ||||
-rw-r--r-- | src/main.c | 15 | ||||
-rw-r--r-- | src/malloc.c | 2 | ||||
-rw-r--r-- | src/palette.c | 8 | ||||
-rw-r--r-- | src/save.c | 6 | ||||
-rw-r--r-- | src/start_menu.c | 231 | ||||
-rw-r--r-- | src/text.c | 2 | ||||
-rw-r--r-- | src/window.c | 2 |
11 files changed, 1979 insertions, 664 deletions
diff --git a/src/battle_4.c b/src/battle_4.c new file mode 100644 index 000000000..d6f1cd1f5 --- /dev/null +++ b/src/battle_4.c @@ -0,0 +1,595 @@ +#include "global.h" +#include "battle.h" + +void atk00_attackcanceler(void); +void atk01_accuracycheck(void); +void atk02_attackstring(void); +void atk03_ppreduce(void); +void atk04_critcalc(void); +void atk05_damagecalc1(void); +void atk06_typecalc(void); +void atk07_dmg_adjustment(void); +void atk08_dmg_adjustment2(void); +void atk09_attackanimation(void); +void atk0A_waitanimation(void); +void atk0B_healthbarupdate(void); +void atk0C_datahpupdate(void); +void atk0D_critmessage(void); +void atk0E_effectiveness_sound(void); +void atk0F_resultmessage(void); +void atk10_printstring(void); +void atk11_printstring_playeronly(void); +void atk12_waitmessage(void); +void atk13_printfromtable(void); +void atk14_printfromtable_playeronly(void); +void atk15_seteffectwithchancetarget(void); +void atk16_seteffectprimary(void); +void atk17_seteffectsecondary(void); +void atk18_status_effect_clear(void); +void atk19_faint_pokemon(void); +void atk1A_faint_animation(void); +void atk1B_faint_effects_clear(void); +void atk1C_jumpifstatus(void); +void atk1D_jumpifstatus2(void); +void atk1E_jumpifability(void); +void atk1F_jumpifsideaffecting(void); +void atk20_jumpifstat(void); +void atk21_jumpifstatus3(void); +void atk22_jumpiftype(void); +void atk23_getexp(void); +void atk24(void); +void atk25_move_values_cleanup(void); +void atk26_set_multihit(void); +void atk27_decrement_multihit(void); +void atk28_goto(void); +void atk29_jumpifbyte(void); +void atk2A_jumpifhalfword(void); +void atk2B_jumpifword(void); +void atk2C_jumpifarrayequal(void); +void atk2D_jumpifarraynotequal(void); +void atk2E_setbyte(void); +void atk2F_addbyte(void); +void atk30_subbyte(void); +void atk31_copyarray(void); +void atk32_copyarray_withindex(void); +void atk33_orbyte(void); +void atk34_orhalfword(void); +void atk35_orword(void); +void atk36_bicbyte(void); +void atk37_bichalfword(void); +void atk38_bicword(void); +void atk39_pause(void); +void atk3A_waitstate(void); +void atk3B_healthbar_update(void); +void atk3C_return(void); +void atk3D_end(void); +void atk3E_end2(void); +void atk3F_end3(void); +void atk40_jump_if_move_affected_by_protect(void); +void atk41_call(void); +void atk42_jumpiftype2(void); +void atk43_jumpifabilitypresent(void); +void atk44(void); +void atk45_playanimation(void); +void atk46_playanimation2(void); +void atk47_setgraphicalstatchangevalues(void); +void atk48_playstatchangeanimation(void); +void atk49_moveendturn(void); +void atk4A_typecalc2(void); +void atk4B_return_atk_to_ball(void); +void atk4C_copy_poke_data(void); +void atk4D_switch_data_update(void); +void atk4E_switchin_anim(void); +void atk4F_jump_if_cannot_switch(void); +void atk50_openpartyscreen(void); +void atk51_switch_handle_order(void); +void atk52_switch_in_effects(void); +void atk53_trainer_slide(void); +void atk54_effectiveness_sound(void); +void atk55_play_sound(void); +void atk56_fainting_cry(void); +void atk57(void); +void atk58_return_to_ball(void); +void atk59_learnmove_inbattle(void); +void atk5A(void); +void atk5B_80256E0(void); +void atk5C_hitanimation(void); +void atk5D_getmoneyreward(void); +void atk5E_8025A70(void); +void atk5F_8025B24(void); +void atk60_increment_gamestat(void); +void atk61_8025BA4(void); +void atk62_08025C6C(void); +void atk63_jumptorandomattack(void); +void atk64_statusanimation(void); +void atk65_status2animation(void); +void atk66_chosenstatusanimation(void); +void atk67_8025ECC(void); +void atk68_80246A0(void); +void atk69_dmg_adjustment2(void); +void atk6A_removeitem(void); +void atk6B_atknameinbuff1(void); +void atk6C_lvlbox_display(void); +void atk6D_set_sentpokes_values(void); +void atk6E_set_atk_to_player0(void); +void atk6F_set_visible(void); +void atk70_record_ability(void); +void atk71_buffer_move_to_learn(void); +void atk72_jump_if_can_run_frombattle(void); +void atk73_hp_thresholds(void); +void atk74_hp_thresholds2(void); +void atk75_8026A58(void); +void atk76_various(void); +void atk77_setprotect(void); +void atk78_faintifabilitynotdamp(void); +void atk79_setatkhptozero(void); +void atk7A_jumpwhiletargetvalid(void); +void atk7B_healhalfHP_if_possible(void); +void atk7C_8025508(void); +void atk7D_set_rain(void); +void atk7E_setreflect(void); +void atk7F_setseeded(void); +void atk80_manipulatedamage(void); +void atk81_setrest(void); +void atk82_jumpifnotfirstturn(void); +void atk83_nop(void); +void atk84_jump_if_cant_sleep(void); +void atk85_stockpile(void); +void atk86_stockpiletobasedamage(void); +void atk87_stockpiletohpheal(void); +void atk88_negativedamage(void); +void atk89_statbuffchange(void); +void atk8A_normalisebuffs(void); +void atk8B_setbide(void); +void atk8C_confuseifrepeatingattackends(void); +void atk8D_setmultihit_counter(void); +void atk8E_prepare_multihit(void); +void atk8F_forcerandomswitch(void); +void atk90_conversion_type_change(void); +void atk91_givepaydaymoney(void); +void atk92_setlightscreen(void); +void atk93_ko_move(void); +void atk94_gethalfcurrentenemyhp(void); +void atk95_setsandstorm(void); +void atk96_weatherdamage(void); +void atk97_try_infatuation(void); +void atk98_status_icon_update(void); +void atk99_setmist(void); +void atk9A_set_focusenergy(void); +void atk9B_transformdataexecution(void); +void atk9C_set_substitute(void); +void atk9D_copyattack(void); +void atk9E_metronome(void); +void atk9F_dmgtolevel(void); +void atkA0_psywavedamageeffect(void); +void atkA1_counterdamagecalculator(void); +void atkA2_mirrorcoatdamagecalculator(void); +void atkA3_disablelastusedattack(void); +void atkA4_setencore(void); +void atkA5_painsplitdmgcalc(void); +void atkA6_settypetorandomresistance(void); +void atkA7_setalwayshitflag(void); +void atkA8_copymovepermanently(void); +void atkA9_sleeptalk_choose_move(void); +void atkAA_set_destinybond(void); +void atkAB_DestinyBondFlagUpdate(void); +void atkAC_remaininghptopower(void); +void atkAD_spite_ppreduce(void); +void atkAE_heal_party_status(void); +void atkAF_cursetarget(void); +void atkB0_set_spikes(void); +void atkB1_set_foresight(void); +void atkB2_setperishsong(void); +void atkB3_rolloutdamagecalculation(void); +void atkB4_jumpifconfusedandstatmaxed(void); +void atkB5_furycuttercalc(void); +void atkB6_happinesstodamagecalculation(void); +void atkB7_presentdamagecalculation(void); +void atkB8_set_safeguard(void); +void atkB9_magnitudedamagecalculation(void); +void atkBA_jumpifnopursuitswitchdmg(void); +void atkBB_setsunny(void); +void atkBC_maxattackhalvehp(void); +void atkBD_copyfoestats(void); +void atkBE_breakfree(void); +void atkBF_set_defense_curl(void); +void atkC0_recoverbasedonsunlight(void); +void atkC1_hidden_power(void); +void atkC2_selectnexttarget(void); +void atkC3_setfutureattack(void); +void atkC4_beat_up(void); +void atkC5_hidepreattack(void); +void atkC6_unhidepostattack(void); +void atkC7_setminimize(void); +void atkC8_sethail(void); +void atkC9_jumpifattackandspecialattackcannotfall(void); +void atkCA_setforcedtarget(void); +void atkCB_setcharge(void); +void atkCC_callterrainattack(void); +void atkCD_cureifburnedparalysedorpoisoned(void); +void atkCE_settorment(void); +void atkCF_jumpifnodamage(void); +void atkD0_settaunt(void); +void atkD1_set_helpinghand(void); +void atkD2_swap_items(void); +void atkD3_copy_ability(void); +void atkD4_wish_effect(void); +void atkD5_setroots(void); +void atkD6_doubledamagedealtifdamaged(void); +void atkD7_setyawn(void); +void atkD8_setdamagetohealthdifference(void); +void atkD9_scaledamagebyhealthratio(void); +void atkDA_abilityswap(void); +void atkDB_imprisoneffect(void); +void atkDC_setgrudge(void); +void atkDD_weightdamagecalculation(void); +void atkDE_asistattackselect(void); +void atkDF_setmagiccoat(void); +void atkE0_setstealstatchange(void); +void atkE1_intimidate_string_loader(void); +void atkE2_switchout_abilities(void); +void atkE3_jumpiffainted(void); +void atkE4_getsecretpowereffect(void); +void atkE5_pickup(void); +void atkE6_castform_change_animation(void); +void atkE7_castform_data_change(void); +void atkE8_settypebasedhalvers(void); +void atkE9_setweatherballtype(void); +void atkEA_recycleitem(void); +void atkEB_settypetoterrain(void); +void atkEC_pursuit_sth(void); +void atkED_802B4B4(void); +void atkEE_removelightscreenreflect(void); +void atkEF_pokeball_catch_calculation(void); +void atkF0_copy_caught_poke(void); +void atkF1_setpoke_as_caught(void); +void atkF2_display_dex_info(void); +void atkF3_nickname_caught_poke(void); +void atkF4_802BEF0(void); +void atkF5_removeattackerstatus1(void); +void atkF6_802BF48(void); +void atkF7_802BF54(void); +void sub_8056EF8(void); + +void (* const gBattleScriptingCommandsTable[])(void) = +{ + atk00_attackcanceler, + atk01_accuracycheck, + atk02_attackstring, + atk03_ppreduce, + atk04_critcalc, + atk05_damagecalc1, + atk06_typecalc, + atk07_dmg_adjustment, + atk08_dmg_adjustment2, + atk09_attackanimation, + atk0A_waitanimation, + atk0B_healthbarupdate, + atk0C_datahpupdate, + atk0D_critmessage, + atk0E_effectiveness_sound, + atk0F_resultmessage, + atk10_printstring, + atk11_printstring_playeronly, + atk12_waitmessage, + atk13_printfromtable, + atk14_printfromtable_playeronly, + atk15_seteffectwithchancetarget, + atk16_seteffectprimary, + atk17_seteffectsecondary, + atk18_status_effect_clear, + atk19_faint_pokemon, + atk1A_faint_animation, + atk1B_faint_effects_clear, + atk1C_jumpifstatus, + atk1D_jumpifstatus2, + atk1E_jumpifability, + atk1F_jumpifsideaffecting, + atk20_jumpifstat, + atk21_jumpifstatus3, + atk22_jumpiftype, + atk23_getexp, + atk24, + atk25_move_values_cleanup, + atk26_set_multihit, + atk27_decrement_multihit, + atk28_goto, + atk29_jumpifbyte, + atk2A_jumpifhalfword, + atk2B_jumpifword, + atk2C_jumpifarrayequal, + atk2D_jumpifarraynotequal, + atk2E_setbyte, + atk2F_addbyte, + atk30_subbyte, + atk31_copyarray, + atk32_copyarray_withindex, + atk33_orbyte, + atk34_orhalfword, + atk35_orword, + atk36_bicbyte, + atk37_bichalfword, + atk38_bicword, + atk39_pause, + atk3A_waitstate, + atk3B_healthbar_update, + atk3C_return, + atk3D_end, + atk3E_end2, + atk3F_end3, + atk40_jump_if_move_affected_by_protect, + atk41_call, + atk42_jumpiftype2, + atk43_jumpifabilitypresent, + atk44, + atk45_playanimation, + atk46_playanimation2, + atk47_setgraphicalstatchangevalues, + atk48_playstatchangeanimation, + atk49_moveendturn, + atk4A_typecalc2, + atk4B_return_atk_to_ball, + atk4C_copy_poke_data, + atk4D_switch_data_update, + atk4E_switchin_anim, + atk4F_jump_if_cannot_switch, + atk50_openpartyscreen, + atk51_switch_handle_order, + atk52_switch_in_effects, + atk53_trainer_slide, + atk54_effectiveness_sound, + atk55_play_sound, + atk56_fainting_cry, + atk57, + atk58_return_to_ball, + atk59_learnmove_inbattle, + atk5A, + atk5B_80256E0, + atk5C_hitanimation, + atk5D_getmoneyreward, + atk5E_8025A70, + atk5F_8025B24, + atk60_increment_gamestat, + atk61_8025BA4, + atk62_08025C6C, + atk63_jumptorandomattack, + atk64_statusanimation, + atk65_status2animation, + atk66_chosenstatusanimation, + atk67_8025ECC, + atk68_80246A0, + atk69_dmg_adjustment2, + atk6A_removeitem, + atk6B_atknameinbuff1, + atk6C_lvlbox_display, + atk6D_set_sentpokes_values, + atk6E_set_atk_to_player0, + atk6F_set_visible, + atk70_record_ability, + atk71_buffer_move_to_learn, + atk72_jump_if_can_run_frombattle, + atk73_hp_thresholds, + atk74_hp_thresholds2, + atk75_8026A58, + atk76_various, + atk77_setprotect, + atk78_faintifabilitynotdamp, + atk79_setatkhptozero, + atk7A_jumpwhiletargetvalid, + atk7B_healhalfHP_if_possible, + atk7C_8025508, + atk7D_set_rain, + atk7E_setreflect, + atk7F_setseeded, + atk80_manipulatedamage, + atk81_setrest, + atk82_jumpifnotfirstturn, + atk83_nop, + atk84_jump_if_cant_sleep, + atk85_stockpile, + atk86_stockpiletobasedamage, + atk87_stockpiletohpheal, + atk88_negativedamage, + atk89_statbuffchange, + atk8A_normalisebuffs, + atk8B_setbide, + atk8C_confuseifrepeatingattackends, + atk8D_setmultihit_counter, + atk8E_prepare_multihit, + atk8F_forcerandomswitch, + atk90_conversion_type_change, + atk91_givepaydaymoney, + atk92_setlightscreen, + atk93_ko_move, + atk94_gethalfcurrentenemyhp, + atk95_setsandstorm, + atk96_weatherdamage, + atk97_try_infatuation, + atk98_status_icon_update, + atk99_setmist, + atk9A_set_focusenergy, + atk9B_transformdataexecution, + atk9C_set_substitute, + atk9D_copyattack, + atk9E_metronome, + atk9F_dmgtolevel, + atkA0_psywavedamageeffect, + atkA1_counterdamagecalculator, + atkA2_mirrorcoatdamagecalculator, + atkA3_disablelastusedattack, + atkA4_setencore, + atkA5_painsplitdmgcalc, + atkA6_settypetorandomresistance, + atkA7_setalwayshitflag, + atkA8_copymovepermanently, + atkA9_sleeptalk_choose_move, + atkAA_set_destinybond, + atkAB_DestinyBondFlagUpdate, + atkAC_remaininghptopower, + atkAD_spite_ppreduce, + atkAE_heal_party_status, + atkAF_cursetarget, + atkB0_set_spikes, + atkB1_set_foresight, + atkB2_setperishsong, + atkB3_rolloutdamagecalculation, + atkB4_jumpifconfusedandstatmaxed, + atkB5_furycuttercalc, + atkB6_happinesstodamagecalculation, + atkB7_presentdamagecalculation, + atkB8_set_safeguard, + atkB9_magnitudedamagecalculation, + atkBA_jumpifnopursuitswitchdmg, + atkBB_setsunny, + atkBC_maxattackhalvehp, + atkBD_copyfoestats, + atkBE_breakfree, + atkBF_set_defense_curl, + atkC0_recoverbasedonsunlight, + atkC1_hidden_power, + atkC2_selectnexttarget, + atkC3_setfutureattack, + atkC4_beat_up, + atkC5_hidepreattack, + atkC6_unhidepostattack, + atkC7_setminimize, + atkC8_sethail, + atkC9_jumpifattackandspecialattackcannotfall, + atkCA_setforcedtarget, + atkCB_setcharge, + atkCC_callterrainattack, + atkCD_cureifburnedparalysedorpoisoned, + atkCE_settorment, + atkCF_jumpifnodamage, + atkD0_settaunt, + atkD1_set_helpinghand, + atkD2_swap_items, + atkD3_copy_ability, + atkD4_wish_effect, + atkD5_setroots, + atkD6_doubledamagedealtifdamaged, + atkD7_setyawn, + atkD8_setdamagetohealthdifference, + atkD9_scaledamagebyhealthratio, + atkDA_abilityswap, + atkDB_imprisoneffect, + atkDC_setgrudge, + atkDD_weightdamagecalculation, + atkDE_asistattackselect, + atkDF_setmagiccoat, + atkE0_setstealstatchange, + atkE1_intimidate_string_loader, + atkE2_switchout_abilities, + atkE3_jumpiffainted, + atkE4_getsecretpowereffect, + atkE5_pickup, + atkE6_castform_change_animation, + atkE7_castform_data_change, + atkE8_settypebasedhalvers, + atkE9_setweatherballtype, + atkEA_recycleitem, + atkEB_settypetoterrain, + atkEC_pursuit_sth, + atkED_802B4B4, + atkEE_removelightscreenreflect, + atkEF_pokeball_catch_calculation, + atkF0_copy_caught_poke, + atkF1_setpoke_as_caught, + atkF2_display_dex_info, + atkF3_nickname_caught_poke, + atkF4_802BEF0, + atkF5_removeattackerstatus1, + atkF6_802BF48, + atkF7_802BF54, + sub_8056EF8 +}; + +struct statFractions +{ + u8 dividend; + u8 divisor; +}; + +const struct statFractions gAccuracyStageRatios[] = +{ + { 33, 100}, // -6 + { 36, 100}, // -5 + { 43, 100}, // -4 + { 50, 100}, // -3 + { 60, 100}, // -2 + { 75, 100}, // -1 + { 1, 1}, // 0 + {133, 100}, // +1 + {166, 100}, // +2 + { 2, 1}, // +3 + {233, 100}, // +4 + {133, 50}, // +5 + { 3, 1}, // +6 +}; + +// The chance is 1/N for each stage. +const u16 gCriticalHitChance[] = {16, 8, 4, 3, 2}; + +const u32 gStatusFlagsForMoveEffects[] = +{ + 0x00000000, + 0x00000007, + 0x00000008, + 0x00000010, + 0x00000020, + 0x00000040, + 0x00000080, + 0x00000007, + 0x00000008, + 0x00000000, + 0x00000070, + 0x00000000, + 0x00001000, + 0x0000E000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00400000, + 0x00000000, + 0x00000000, + 0x04000000, + 0x08000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000C00, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; diff --git a/src/battle_ai.c b/src/battle_ai.c index 7c4b7604d..699ba5095 100644 --- a/src/battle_ai.c +++ b/src/battle_ai.c @@ -1,32 +1,36 @@ #include "global.h" +#include "battle_ai.h" #include "pokemon.h" #include "battle.h" #include "species.h" #include "abilities.h" +#include "rng.h" +#include "item.h" +#include "battle_move_effects.h" #define AIScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24) #define AIScriptRead16(ptr) ((ptr)[0] | (ptr)[1] << 8) #define AIScriptRead8(ptr) ((ptr)[0]) #define AIScriptReadPtr(ptr) (u8*) AIScriptRead32(ptr) -#define AI_THINKING_STRUCT ((struct AI_ThinkingStruct *)(gBattleResources->ai)) -#define UNK_2016A00_STRUCT ((struct UnknownStruct2 *)(gBattleResources->unk18)) -#define UNK_2016C00_STRUCT ((struct UnknownStruct4 *)(gBattleResources->unk1C)) -#define UNK_BATTLE_STRUCT ((struct UnknownStruct1 *)(gBattleResources)) - -#define AI_ACTION_UNK1 0x0001 -#define AI_ACTION_UNK2 0x0002 -#define AI_ACTION_UNK3 0x0004 -#define AI_ACTION_UNK4 0x0008 +#define AI_ACTION_DONE 0x0001 +#define AI_ACTION_FLEE 0x0002 +#define AI_ACTION_WATCH 0x0004 +#define AI_ACTION_DO_NOT_ATTACK 0x0008 #define AI_ACTION_UNK5 0x0010 #define AI_ACTION_UNK6 0x0020 #define AI_ACTION_UNK7 0x0040 #define AI_ACTION_UNK8 0x0080 +#define AI_THINKING_STRUCT ((struct AI_ThinkingStruct *)(gBattleResources->ai)) +#define BATTLE_HISTORY ((struct BattleHistory *)(gBattleResources->battleHistory)) + enum { - TARGET, - USER + AI_TARGET, + AI_USER, + AI_TARGET_PARTNER, + AI_USER_PARTNER }; // AI states @@ -38,128 +42,6 @@ enum AIState_DoNotProcess }; -//Copied from pokeruby -- hopefully the same -struct Trainer -{ - /*0x00*/ u8 partyFlags; - /*0x01*/ u8 trainerClass; - /*0x02*/ u8 encounterMusic:7; - /*0x02*/ u8 gender:1; - /*0x03*/ u8 trainerPic; - /*0x04*/ u8 trainerName[12]; - /*0x10*/ u16 items[4]; - /*0x18*/ bool8 doubleBattle; - /*0x1C*/ u32 aiFlags; - /*0x20*/ u8 partySize; - /*0x24*/ void *party; -}; - -#define POKEMON_NAME_LENGTH 10 - -struct BattlePokemon -{ - /* 0x00 */ u16 species; - /* 0x02 */ u16 attack; - /* 0x04 */ u16 defense; - /* 0x06 */ u16 speed; - /* 0x08 */ u16 spAttack; - /* 0x0A */ u16 spDefense; - /* 0x0C */ u16 moves[4]; - /* 0x14 */ u32 hpIV:5; - /* 0x14 */ u32 attackIV:5; - /* 0x15 */ u32 defenseIV:5; - /* 0x15 */ u32 speedIV:5; - /* 0x16 */ u32 spAttackIV:5; - /* 0x17 */ u32 spDefenseIV:5; - /* 0x17 */ u32 isEgg:1; - /* 0x17 */ u32 altAbility:1; - /* 0x18 */ s8 statStages[8]; - /* 0x20 */ u8 ability; - /* 0x21 */ u8 type1; - /* 0x22 */ u8 type2; - /* 0x23 */ u8 unknown; - /* 0x24 */ u8 pp[4]; - /* 0x28 */ u16 hp; - /* 0x2A */ u8 level; - /* 0x2B */ u8 friendship; - /* 0x2C */ u16 maxHP; - /* 0x2E */ u16 item; - /* 0x30 */ u8 nickname[POKEMON_NAME_LENGTH + 1]; - /* 0x3B */ u8 ppBonuses; - /* 0x3C */ u8 otName[8]; - /* 0x44 */ u32 experience; - /* 0x48 */ u32 personality; - /* 0x4C */ u32 status1; - /* 0x50 */ u32 status2; - /* 0x54 */ u32 otId; -}; - -//size should be 0x1C -struct AI_ThinkingStruct -{ - u8 aiState; - u8 movesetIndex; - u16 moveConsidered; - s8 score[4]; - u32 funcResult; - u32 aiFlags; - u8 aiAction; - u8 aiLogicId; - u8 filler12[6]; - u8 unk18[4]; -}; - -//size should be 0x54 -struct UnknownStruct2 -{ - u16 unk0[2][8]; - u8 unk20[2]; - u8 filler20[0x1E]; - u8 unk40[4]; - u8 unk44[4]; - u16 unk48[4]; - u8 unk50; -}; - -struct UnknownStruct4 -{ - u8 *ptr[8]; - u8 unk20; -}; - -struct SimpleUnknownStruct -{ - u32 unkArray[4]; // unknown size -}; - -struct UnknownStruct1 -{ - u8 unk0; - u8 filler1[0x3]; - struct SimpleUnknownStruct *unk4; - u8 filler8[0xC]; - struct AI_ThinkingStruct *ai; - struct UnknownStruct2 *unk18; - struct UnknownStruct4 *unk1C; -}; - -struct UnknownStruct5 -{ - u8 filler0[0x3]; - u16 unk4; - u16 unk6; - u8 unk8; - u8 unk9; - u8 fillerA[0x9]; - u8 taunt:4; - u8 unkC:4; - u8 fillerD[0x2]; - u8 unk16; - u8 filler17[0x4]; -}; - -extern struct UnknownStruct5 gDisableStructs[]; - /* gAIScriptPtr is a pointer to the next battle AI cmd command to read. when a command finishes processing, gAIScriptPtr is incremented by @@ -167,168 +49,388 @@ 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. */ -extern u8 *gAIScriptPtr; extern u32 gBattleTypeFlags; extern u8 gActiveBank; -extern struct BattlePokemon gBattleMons[]; +extern struct BattlePokemon gBattleMons[4]; extern u16 gCurrentMove; extern u8 gBankTarget; extern u8 gAbsentBankFlags; -extern u16 gUnknown_02024248[]; -extern u8 *gBattleStruct; -extern struct UnknownStruct1 *gBattleResources; -extern u16 gUnknown_02038BCA; -extern u16 gUnknown_02038BCC; -extern u8 gPlayerMonIndex; -extern struct Trainer gTrainers[]; -extern const u32 gBitTable[]; -extern u8 *gUnknown_082DBEF8[]; -extern u32 gStatuses3[]; -extern u16 gUnknown_0202428E[]; -extern struct BattleMove gBattleMoves[]; -extern u8 gUnknown_03005D10[]; -extern u8 gBattlePartyID[][2]; -extern struct BaseStats gBaseStats[]; -extern u16 gUnknown_02024400; -extern u8 gBattleScripting[]; +extern u16 gLastUsedMovesByBanks[4]; +extern u16 gTrainerBattleOpponent_A; +extern u16 gTrainerBattleOpponent_B; +extern u32 gStatuses3[4]; +extern u16 gSideAffecting[2]; +extern u16 gBattlePartyID[4]; +extern u16 gDynamicBasePower; extern u8 gBattleMoveFlags; -extern int gBattleMoveDamage; +extern s32 gBattleMoveDamage; extern u8 gCritMultiplier; extern u16 gBattleWeather; +extern const struct BattleMove gBattleMoves[]; +extern const struct BaseStats gBaseStats[]; +extern const u32 gBitTable[]; +extern u8 * const gBattleAI_ScriptsTable[]; + extern u8 GetBankIdentity(u8); extern u8 b_first_side(u8, u8, u8); extern u8 GetBankByPlayerAI(u8); -extern void move_effectiveness_something(u16, u8, u8); -extern u8 ItemId_GetHoldEffect(); -extern void b_mc_stack_push(u8 *); -extern bool8 b_mc_stack_pop_cursor(void); -extern void sub_8046E7C(u8, u8); +extern void TypeCalc(u16 move, u8 bankAtk, u8 bankDef); +extern void AI_CalcDmg(u8, u8); + +extern u8 CheckMoveLimitations(); +extern u32 GetAiScriptsInRecordedBattle(); +extern u32 GetAiScriptsInBattleFactory(); + +static u8 BattleAI_ChooseMoveOrAction_Singles(void); +static u8 BattleAI_ChooseMoveOrAction_Doubles(void); +static void RecordLastUsedMoveByTarget(void); +static void BattleAI_DoAIProcessing(void); +static void AIStackPushVar(u8 *); +static bool8 AIStackPop(void); + +static void BattleAICmd_if_random_less_than(void); +static void BattleAICmd_if_random_greater_than(void); +static void BattleAICmd_if_random_equal(void); +static void BattleAICmd_if_random_not_equal(void); +static void BattleAICmd_score(void); +static void BattleAICmd_if_hp_less_than(void); +static void BattleAICmd_if_hp_more_than(void); +static void BattleAICmd_if_hp_equal(void); +static void BattleAICmd_if_hp_not_equal(void); +static void BattleAICmd_if_status(void); +static void BattleAICmd_if_not_status(void); +static void BattleAICmd_if_status2(void); +static void BattleAICmd_if_not_status2(void); +static void BattleAICmd_if_status3(void); +static void BattleAICmd_if_not_status3(void); +static void BattleAICmd_if_side_affecting(void); +static void BattleAICmd_if_not_side_affecting(void); +static void BattleAICmd_if_less_than(void); +static void BattleAICmd_if_more_than(void); +static void BattleAICmd_if_equal(void); +static void BattleAICmd_if_not_equal(void); +static void BattleAICmd_if_less_than_32(void); +static void BattleAICmd_if_more_than_32(void); +static void BattleAICmd_if_equal_32(void); +static void BattleAICmd_if_not_equal_32(void); +static void BattleAICmd_if_move(void); +static void BattleAICmd_if_not_move(void); +static void BattleAICmd_if_in_bytes(void); +static void BattleAICmd_if_not_in_bytes(void); +static void BattleAICmd_if_in_words(void); +static void BattleAICmd_if_not_in_words(void); +static void BattleAICmd_if_user_can_damage(void); +static void BattleAICmd_if_user_cant_damage(void); +static void BattleAICmd_get_turn_count(void); +static void BattleAICmd_get_type(void); +static void BattleAICmd_get_last_used_bank_move_power(void); +static void BattleAICmd_is_most_powerful_move(void); +static void BattleAICmd_get_last_used_bank_move(void); +static void BattleAICmd_if_arg_equal(void); +static void BattleAICmd_if_arg_not_equal(void); +static void BattleAICmd_if_would_go_first(void); +static void BattleAICmd_if_would_not_go_first(void); +static void BattleAICmd_nullsub_2A(void); +static void BattleAICmd_nullsub_2B(void); +static void BattleAICmd_count_alive_pokemon(void); +static void BattleAICmd_get_considered_move(void); +static void BattleAICmd_get_considered_move_effect(void); +static void BattleAICmd_get_ability(void); +static void BattleAICmd_get_highest_type_effectiveness(void); +static void BattleAICmd_if_type_effectiveness(void); +static void BattleAICmd_nullsub_32(void); +static void BattleAICmd_nullsub_33(void); +static void BattleAICmd_if_status_in_party(void); +static void BattleAICmd_if_status_not_in_party(void); +static void BattleAICmd_get_weather(void); +static void BattleAICmd_if_effect(void); +static void BattleAICmd_if_not_effect(void); +static void BattleAICmd_if_stat_level_less_than(void); +static void BattleAICmd_if_stat_level_more_than(void); +static void BattleAICmd_if_stat_level_equal(void); +static void BattleAICmd_if_stat_level_not_equal(void); +static void BattleAICmd_if_can_faint(void); +static void BattleAICmd_if_cant_faint(void); +static void BattleAICmd_if_has_move(void); +static void BattleAICmd_if_dont_have_move(void); +static void BattleAICmd_if_move_effect(void); +static void BattleAICmd_if_not_move_effect(void); +static void BattleAICmd_if_any_move_disabled_or_encored(void); +static void BattleAICmd_if_curr_move_disabled_or_encored(void); +static void BattleAICmd_flee(void); +static void BattleAICmd_if_random_100(void); +static void BattleAICmd_watch(void); +static void BattleAICmd_get_hold_effect(void); +static void BattleAICmd_get_gender(void); +static void BattleAICmd_is_first_turn(void); +static void BattleAICmd_get_stockpile_count(void); +static void BattleAICmd_is_double_battle(void); +static void BattleAICmd_get_used_held_item(void); +static void BattleAICmd_get_move_type_from_result(void); +static void BattleAICmd_get_move_power_from_result(void); +static void BattleAICmd_get_move_effect_from_result(void); +static void BattleAICmd_get_protect_count(void); +static void BattleAICmd_nullsub_52(void); +static void BattleAICmd_nullsub_53(void); +static void BattleAICmd_nullsub_54(void); +static void BattleAICmd_nullsub_55(void); +static void BattleAICmd_nullsub_56(void); +static void BattleAICmd_nullsub_57(void); +static void BattleAICmd_call(void); +static void BattleAICmd_jump(void); +static void BattleAICmd_end(void); +static void BattleAICmd_if_level_cond(void); +static void BattleAICmd_if_target_taunted(void); +static void BattleAICmd_if_target_not_taunted(void); +static void BattleAICmd_check_ability(void); +static void BattleAICmd_is_of_type(void); +static void BattleAICmd_if_target_is_ally(void); +static void BattleAICmd_if_flash_fired(void); +static void BattleAICmd_if_holds_item(void); + +// ewram + +EWRAM_DATA u8 *gAIScriptPtr = NULL; +EWRAM_DATA static u8 sBank_AI = 0; + +// const rom data typedef void (*BattleAICmdFunc)(void); -extern const BattleAICmdFunc sBattleAICmdTable[]; - -extern u8 sub_803FECC(); -extern u16 Random(); -extern u8 GetBankSide(); -extern u32 sub_8186438(); -extern u32 sub_81A6FB4(); +static const BattleAICmdFunc sBattleAICmdTable[] = +{ + BattleAICmd_if_random_less_than, // 0x0 + BattleAICmd_if_random_greater_than, // 0x1 + BattleAICmd_if_random_equal, // 0x2 + BattleAICmd_if_random_not_equal, // 0x3 + BattleAICmd_score, // 0x4 + BattleAICmd_if_hp_less_than, // 0x5 + BattleAICmd_if_hp_more_than, // 0x6 + BattleAICmd_if_hp_equal, // 0x7 + BattleAICmd_if_hp_not_equal, // 0x8 + BattleAICmd_if_status, // 0x9 + BattleAICmd_if_not_status, // 0xA + BattleAICmd_if_status2, // 0xB + BattleAICmd_if_not_status2, // 0xC + BattleAICmd_if_status3, // 0xD + BattleAICmd_if_not_status3, // 0xE + BattleAICmd_if_side_affecting, // 0xF + BattleAICmd_if_not_side_affecting, // 0x10 + BattleAICmd_if_less_than, // 0x11 + BattleAICmd_if_more_than, // 0x12 + BattleAICmd_if_equal, // 0x13 + BattleAICmd_if_not_equal, // 0x14 + BattleAICmd_if_less_than_32, // 0x15 + BattleAICmd_if_more_than_32, // 0x16 + BattleAICmd_if_equal_32, // 0x17 + BattleAICmd_if_not_equal_32, // 0x18 + BattleAICmd_if_move, // 0x19 + BattleAICmd_if_not_move, // 0x1A + BattleAICmd_if_in_bytes, // 0x1B + BattleAICmd_if_not_in_bytes, // 0x1C + BattleAICmd_if_in_words, // 0x1D + BattleAICmd_if_not_in_words, // 0x1E + BattleAICmd_if_user_can_damage, // 0x1F + BattleAICmd_if_user_cant_damage, // 0x20 + BattleAICmd_get_turn_count, // 0x21 + BattleAICmd_get_type, // 0x22 + BattleAICmd_get_last_used_bank_move_power, // 0x23 + BattleAICmd_is_most_powerful_move, // 0x24 + BattleAICmd_get_last_used_bank_move, // 0x25 + BattleAICmd_if_arg_equal, // 0x26 + BattleAICmd_if_arg_not_equal, // 0x27 + BattleAICmd_if_would_go_first, // 0x28 + BattleAICmd_if_would_not_go_first, // 0x29 + BattleAICmd_nullsub_2A, // 0x2A + BattleAICmd_nullsub_2B, // 0x2B + BattleAICmd_count_alive_pokemon, // 0x2C + BattleAICmd_get_considered_move, // 0x2D + BattleAICmd_get_considered_move_effect, // 0x2E + BattleAICmd_get_ability, // 0x2F + BattleAICmd_get_highest_type_effectiveness, // 0x30 + BattleAICmd_if_type_effectiveness, // 0x31 + BattleAICmd_nullsub_32, // 0x32 + BattleAICmd_nullsub_33, // 0x33 + BattleAICmd_if_status_in_party, // 0x34 + BattleAICmd_if_status_not_in_party, // 0x35 + BattleAICmd_get_weather, // 0x36 + BattleAICmd_if_effect, // 0x37 + BattleAICmd_if_not_effect, // 0x38 + BattleAICmd_if_stat_level_less_than, // 0x39 + BattleAICmd_if_stat_level_more_than, // 0x3A + BattleAICmd_if_stat_level_equal, // 0x3B + BattleAICmd_if_stat_level_not_equal, // 0x3C + BattleAICmd_if_can_faint, // 0x3D + BattleAICmd_if_cant_faint, // 0x3E + BattleAICmd_if_has_move, // 0x3F + BattleAICmd_if_dont_have_move, // 0x40 + BattleAICmd_if_move_effect, // 0x41 + BattleAICmd_if_not_move_effect, // 0x42 + BattleAICmd_if_any_move_disabled_or_encored, // 0x43 + BattleAICmd_if_curr_move_disabled_or_encored, // 0x44 + BattleAICmd_flee, // 0x45 + BattleAICmd_if_random_100, // 0x46 + BattleAICmd_watch, // 0x47 + BattleAICmd_get_hold_effect, // 0x48 + BattleAICmd_get_gender, // 0x49 + BattleAICmd_is_first_turn, // 0x4A + BattleAICmd_get_stockpile_count, // 0x4B + BattleAICmd_is_double_battle, // 0x4C + BattleAICmd_get_used_held_item, // 0x4D + BattleAICmd_get_move_type_from_result, // 0x4E + BattleAICmd_get_move_power_from_result, // 0x4F + BattleAICmd_get_move_effect_from_result, // 0x50 + BattleAICmd_get_protect_count, // 0x51 + BattleAICmd_nullsub_52, // 0x52 + BattleAICmd_nullsub_53, // 0x53 + BattleAICmd_nullsub_54, // 0x54 + BattleAICmd_nullsub_55, // 0x55 + BattleAICmd_nullsub_56, // 0x56 + BattleAICmd_nullsub_57, // 0x57 + BattleAICmd_call, // 0x58 + BattleAICmd_jump, // 0x59 + BattleAICmd_end, // 0x5A + BattleAICmd_if_level_cond, // 0x5B + BattleAICmd_if_target_taunted, // 0x5C + BattleAICmd_if_target_not_taunted, // 0x5D + BattleAICmd_if_target_is_ally, // 0x5E + BattleAICmd_is_of_type, // 0x5F + BattleAICmd_check_ability, // 0x60 + BattleAICmd_if_flash_fired, // 0x61 + BattleAICmd_if_holds_item, // 0x62 +}; -void BattleAI_SetupAIData(u8 a); -u8 BattleAI_GetAIActionToUse(void); -u8 sub_8130CF4(void); -void sub_8131074(void); -void BattleAI_DoAIProcessing(void); +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, + 0xFFFF +}; -void BattleAI_HandleItemUseBeforeAISetup(u8 a) +void BattleAI_HandleItemUseBeforeAISetup(u8 defaultScoreMoves) { s32 i; - u8 *data = (u8 *)gBattleResources->unk18; - - for (i = 0; (u32)i < 0x54; i++) + u8 *data = (u8 *)gBattleResources->battleHistory; + + for (i = 0; i < sizeof(struct BattleHistory); i++) data[i] = 0; - if ((gBattleTypeFlags & 0x0A7F098A) == 8) + // items are allowed to use in ONLY trainer battles + if ((gBattleTypeFlags & + (BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_BATTLE_TOWER | + BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_x2000000 | BATTLE_TYPE_SECRET_BASE)) + == BATTLE_TYPE_TRAINER) { for (i = 0; i < 4; i++) { - if (gTrainers[gUnknown_02038BCA].items[i] != 0) + if (gTrainers[gTrainerBattleOpponent_A].items[i] != 0) { - gBattleResources->unk18->unk48[gBattleResources->unk18->unk50] = gTrainers[gUnknown_02038BCA].items[i]; - gBattleResources->unk18->unk50++; + gBattleResources->battleHistory->TrainerItems[gBattleResources->battleHistory->itemsNo] = gTrainers[gTrainerBattleOpponent_A].items[i]; + gBattleResources->battleHistory->itemsNo++; } } } - - BattleAI_SetupAIData(a); + + BattleAI_SetupAIData(defaultScoreMoves); } -void BattleAI_SetupAIData(u8 a) +void BattleAI_SetupAIData(u8 defaultScoreMoves) { s32 i; u8 *data = (u8 *)AI_THINKING_STRUCT; - u8 r6; + u8 moveLimitations; // clear AI data. - for (i = 0; (u32)i < sizeof(struct AI_ThinkingStruct); i++) + for (i = 0; i < sizeof(struct AI_ThinkingStruct); i++) data[i] = 0; // conditional score reset, unlike Ruby. for (i = 0; i < 4; i++) { - if (a & 1) + if (defaultScoreMoves & 1) AI_THINKING_STRUCT->score[i] = 100; else AI_THINKING_STRUCT->score[i] = 0; - a >>= 1; + defaultScoreMoves >>= 1; } - r6 = sub_803FECC(gActiveBank, 0, 0xFF); + moveLimitations = CheckMoveLimitations(gActiveBank, 0, 0xFF); + // ignore moves that aren't possible to use for (i = 0; i < 4; i++) { - if (gBitTable[i] & r6) + if (gBitTable[i] & moveLimitations) AI_THINKING_STRUCT->score[i] = 0; - AI_THINKING_STRUCT->unk18[i] = 100 - (Random() % 16); + AI_THINKING_STRUCT->simulatedRNG[i] = 100 - (Random() % 16); } - gBattleResources->unk1C->unk20 = 0; - gPlayerMonIndex = gActiveBank; - if (gBattleTypeFlags & 1) + gBattleResources->AI_ScriptsStack->size = 0; + sBank_AI = gActiveBank; + // decide a random target bank in doubles + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { - gBankTarget = (Random() & 2) + ((u32)GetBankSide(gActiveBank) ^ 1); + gBankTarget = (Random() & 2) + (GetBankSide(gActiveBank) ^ 1); if (gAbsentBankFlags & gBitTable[gBankTarget]) gBankTarget ^= 2; } + // in singles there's only one choice else - { - //_08130A60 - gBankTarget = gPlayerMonIndex ^ 1; - } - //_08130A68 - if (gBattleTypeFlags & 0x1000000) - AI_THINKING_STRUCT->aiFlags = sub_8186438(); - else if (gBattleTypeFlags & 0x80) + gBankTarget = sBank_AI ^ 1; + + if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) + AI_THINKING_STRUCT->aiFlags = GetAiScriptsInRecordedBattle(); + else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) AI_THINKING_STRUCT->aiFlags = 0x40000000; - else if (gBattleTypeFlags & 0x400) + else if (gBattleTypeFlags & BATTLE_TYPE_ROAMER) AI_THINKING_STRUCT->aiFlags = 0x20000000; - else if (gBattleTypeFlags & 0x10) + else if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) AI_THINKING_STRUCT->aiFlags = 0x80000000; - else if (gBattleTypeFlags & 0x80000) - AI_THINKING_STRUCT->aiFlags = sub_81A6FB4(); - else if (gBattleTypeFlags & 0x0C3F0900) - AI_THINKING_STRUCT->aiFlags = 7; - else if (gBattleTypeFlags & 0x8000) - AI_THINKING_STRUCT->aiFlags = gTrainers[gUnknown_02038BCA].aiFlags | gTrainers[gUnknown_02038BCC].aiFlags; - else - AI_THINKING_STRUCT->aiFlags = gTrainers[gUnknown_02038BCA].aiFlags; - if (gBattleTypeFlags & 1) - AI_THINKING_STRUCT->aiFlags |= 0x80; + else if (gBattleTypeFlags & BATTLE_TYPE_FACTORY) + AI_THINKING_STRUCT->aiFlags = GetAiScriptsInBattleFactory(); + else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_x4000000 | BATTLE_TYPE_SECRET_BASE)) + AI_THINKING_STRUCT->aiFlags = 7; // the smartest possible set + 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; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + AI_THINKING_STRUCT->aiFlags |= 0x80; // act smart in doubles and don't attack your partner } -u8 sub_8130BA4(void) +u8 BattleAI_ChooseMoveOrAction(void) { - u16 r4 = gCurrentMove; + u16 savedCurrentMove = gCurrentMove; u8 ret; - - if (!(gBattleTypeFlags & 1)) - ret = BattleAI_GetAIActionToUse(); + + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + ret = BattleAI_ChooseMoveOrAction_Singles(); else - ret = sub_8130CF4(); + ret = BattleAI_ChooseMoveOrAction_Doubles(); - gCurrentMove = r4; + gCurrentMove = savedCurrentMove; return ret; } -u8 BattleAI_GetAIActionToUse(void) +static u8 BattleAI_ChooseMoveOrAction_Singles(void) { u8 currentMoveArray[4]; u8 consideredMoveArray[4]; u8 numOfBestMoves; s32 i; - - sub_8131074(); + + RecordLastUsedMoveByTarget(); while (AI_THINKING_STRUCT->aiFlags != 0) { @@ -354,7 +456,7 @@ u8 BattleAI_GetAIActionToUse(void) for (i = 1; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex].moves[i] != 0) // emerald adds an extra move ID check for some reason. + if (gBattleMons[sBank_AI].moves[i] != 0) // emerald adds an extra move ID check for some reason. { // in ruby, the order of these if statements are reversed. if (currentMoveArray[0] == AI_THINKING_STRUCT->score[i]) @@ -374,7 +476,7 @@ u8 BattleAI_GetAIActionToUse(void) } #ifdef NONMATCHING -u8 sub_8130CF4(void) +static u8 BattleAI_ChooseMoveOrAction_Doubles(void) { s32 i; s32 j; @@ -391,10 +493,10 @@ u8 sub_8130CF4(void) //u8 *sp1C = spC; //u8 *sp18 = sp8; //u8 *sp20 = spC; - + for (i = 0; i < 4; i++) //_08130D14 { - if (i == gPlayerMonIndex || gBattleMons[i].hp == 0) + if (i == sBank_AI || gBattleMons[i].hp == 0) { //_08130D2E spC[i] = -1; @@ -409,8 +511,8 @@ u8 sub_8130CF4(void) BattleAI_SetupAIData(0xF); //_08130D76 gBankTarget = i; - if ((i & 1) != (gPlayerMonIndex & 1)) - sub_8131074(); + if ((i & 1) != (sBank_AI & 1)) + RecordLastUsedMoveByTarget(); //_08130D90 AI_THINKING_STRUCT->unk11 = 0; AI_THINKING_STRUCT->unk1 = 0; @@ -439,7 +541,7 @@ u8 sub_8130CF4(void) r5 = 1; for (j = 1; j < 4; j++) { - if (gBattleMons[gPlayerMonIndex].moves[j] != 0) + if (gBattleMons[sBank_AI].moves[j] != 0) { if (sp10[0] == AI_THINKING_STRUCT->score[j]) { @@ -459,15 +561,15 @@ u8 sub_8130CF4(void) spC[i] = sp14[Random() % r5]; //asm("":::"r3"); sp0[i] = sp10[0]; - if (i == (gPlayerMonIndex ^ 2) && sp0[i] < 100) + if (i == (sBank_AI ^ 2) && sp0[i] < 100) sp0[i] = -1; } } //_08130EAE } - + //#define i r5 - + //_08130EC4 r5_2 = sp0[0]; sp8[0] = 0; @@ -493,7 +595,7 @@ u8 sub_8130CF4(void) } #else __attribute__((naked)) -u8 sub_8130CF4(void) +static u8 BattleAI_ChooseMoveOrAction_Doubles(void) { asm(".syntax unified\n\ push {r4-r7,lr}\n\ @@ -513,7 +615,7 @@ u8 sub_8130CF4(void) str r1, [sp, 0x20]\n\ mov r10, sp\n\ _08130D14:\n\ - ldr r0, =gPlayerMonIndex\n\ + ldr r0, =sBank_AI\n\ ldrb r0, [r0]\n\ cmp r8, r0\n\ beq _08130D2E\n\ @@ -561,12 +663,12 @@ _08130D76:\n\ movs r1, 0x1\n\ mov r2, r8\n\ ands r2, r1\n\ - ldr r0, =gPlayerMonIndex\n\ + ldr r0, =sBank_AI\n\ ldrb r0, [r0]\n\ ands r1, r0\n\ cmp r2, r1\n\ beq _08130D90\n\ - bl sub_8131074\n\ + bl RecordLastUsedMoveByTarget\n\ _08130D90:\n\ ldr r2, =gBattleResources\n\ ldr r0, [r2]\n\ @@ -639,7 +741,7 @@ _08130E10:\n\ movs r5, 0x1\n\ movs r3, 0x1\n\ adds r6, r1, 0\n\ - ldr r0, =gPlayerMonIndex\n\ + ldr r0, =sBank_AI\n\ ldrb r1, [r0]\n\ movs r0, 0x58\n\ muls r0, r1\n\ @@ -700,7 +802,7 @@ _08130E72:\n\ ldrb r2, [r6]\n\ mov r0, r10\n\ strh r2, [r0]\n\ - ldr r0, =gPlayerMonIndex\n\ + ldr r0, =sBank_AI\n\ ldrb r1, [r0]\n\ movs r0, 0x2\n\ eors r0, r1\n\ @@ -788,7 +890,7 @@ _08130EFE:\n\ } #endif -void BattleAI_DoAIProcessing(void) +static void BattleAI_DoAIProcessing(void) { while (AI_THINKING_STRUCT->aiState != AIState_FinishedProcessing) { @@ -797,14 +899,14 @@ void BattleAI_DoAIProcessing(void) case AIState_DoNotProcess: //Needed to match. break; case AIState_SettingUp: - gAIScriptPtr = gUnknown_082DBEF8[AI_THINKING_STRUCT->aiLogicId]; // set AI ptr to logic ID. - if (gBattleMons[gPlayerMonIndex].pp[AI_THINKING_STRUCT->movesetIndex] == 0) + gAIScriptPtr = gBattleAI_ScriptsTable[AI_THINKING_STRUCT->aiLogicId]; // set AI ptr to logic ID. + if (gBattleMons[sBank_AI].pp[AI_THINKING_STRUCT->movesetIndex] == 0) { AI_THINKING_STRUCT->moveConsidered = 0; } else { - AI_THINKING_STRUCT->moveConsidered = gBattleMons[gPlayerMonIndex].moves[AI_THINKING_STRUCT->movesetIndex]; + AI_THINKING_STRUCT->moveConsidered = gBattleMons[sBank_AI].moves[AI_THINKING_STRUCT->movesetIndex]; } AI_THINKING_STRUCT->aiState++; break; @@ -814,70 +916,70 @@ void BattleAI_DoAIProcessing(void) else { AI_THINKING_STRUCT->score[AI_THINKING_STRUCT->movesetIndex] = 0; - AI_THINKING_STRUCT->aiAction |= 1; + AI_THINKING_STRUCT->aiAction |= AI_ACTION_DONE; } - if (AI_THINKING_STRUCT->aiAction & 1) + if (AI_THINKING_STRUCT->aiAction & AI_ACTION_DONE) { AI_THINKING_STRUCT->movesetIndex++; - if (AI_THINKING_STRUCT->movesetIndex < 4 && !(AI_THINKING_STRUCT->aiAction & 8)) + if (AI_THINKING_STRUCT->movesetIndex < 4 && !(AI_THINKING_STRUCT->aiAction & AI_ACTION_DO_NOT_ATTACK)) AI_THINKING_STRUCT->aiState = AIState_SettingUp; else AI_THINKING_STRUCT->aiState++; - AI_THINKING_STRUCT->aiAction &= 0xFE; + AI_THINKING_STRUCT->aiAction &= ~(AI_ACTION_DONE); } break; } } } -void sub_8131074(void) +static void RecordLastUsedMoveByTarget(void) { s32 i; - + for (i = 0; i < 4; i++) { - if (gBattleResources->unk18->unk0[gBankTarget][i] == gUnknown_02024248[gBankTarget]) + if (gBattleResources->battleHistory->usedMoves[gBankTarget].moves[i] == gLastUsedMovesByBanks[gBankTarget]) break; - if (gBattleResources->unk18->unk0[gBankTarget][i] != gUnknown_02024248[gBankTarget] //HACK: This redundant condition is a hack to make the asm match. - && gBattleResources->unk18->unk0[gBankTarget][i] == 0) + if (gBattleResources->battleHistory->usedMoves[gBankTarget].moves[i] != gLastUsedMovesByBanks[gBankTarget] //HACK: This redundant condition is a hack to make the asm match. + && gBattleResources->battleHistory->usedMoves[gBankTarget].moves[i] == 0) { - gBattleResources->unk18->unk0[gBankTarget][i] = gUnknown_02024248[gBankTarget]; + gBattleResources->battleHistory->usedMoves[gBankTarget].moves[i] = gLastUsedMovesByBanks[gBankTarget]; break; } } } -void sub_81310F0(u8 a) +void ClearBankMoveHistory(u8 bank) { s32 i; - + for (i = 0; i < 4; i++) - gBattleResources->unk18->unk0[a][i] = 0; + gBattleResources->battleHistory->usedMoves[bank].moves[i] = 0; } -void RecordAbilityBattle(u8 a, u8 b) +void RecordAbilityBattle(u8 bank, u8 abilityId) { - gBattleResources->unk18->unk40[a] = b; + gBattleResources->battleHistory->abilities[bank] = abilityId; } -void sub_8131130(u8 a) +void ClearBankAbilityHistory(u8 bank) { - gBattleResources->unk18->unk40[a] = 0; + gBattleResources->battleHistory->abilities[bank] = 0; } -void b_history__record_item_x12_of_player(u8 a, u8 b) +void RecordItemEffectBattle(u8 bank, u8 itemEffect) { - gBattleResources->unk18->unk44[a] = b; + gBattleResources->battleHistory->itemEffects[bank] = itemEffect; } -void sub_8131160(u8 a) +void ClearBankItemEffectHistory(u8 bank) { - gBattleResources->unk18->unk44[a] = 0; + gBattleResources->battleHistory->itemEffects[bank] = 0; } -void BattleAICmd_if_random_less_than(void) +static void BattleAICmd_if_random_less_than(void) { u16 random = Random(); @@ -887,7 +989,7 @@ void BattleAICmd_if_random_less_than(void) gAIScriptPtr += 6; } -void BattleAICmd_if_random_greater_than(void) +static void BattleAICmd_if_random_greater_than(void) { u16 random = Random(); @@ -897,7 +999,7 @@ void BattleAICmd_if_random_greater_than(void) gAIScriptPtr += 6; } -void BattleAICmd_if_random_equal(void) +static void BattleAICmd_if_random_equal(void) { u16 random = Random(); @@ -907,7 +1009,7 @@ void BattleAICmd_if_random_equal(void) gAIScriptPtr += 6; } -void BattleAICmd_if_random_not_equal(void) +static void BattleAICmd_if_random_not_equal(void) { u16 random = Random(); @@ -917,7 +1019,7 @@ void BattleAICmd_if_random_not_equal(void) gAIScriptPtr += 6; } -void BattleAICmd_score(void) +static void BattleAICmd_score(void) { AI_THINKING_STRUCT->score[AI_THINKING_STRUCT->movesetIndex] += gAIScriptPtr[1]; // add the result to the array of the move consider's score. @@ -927,12 +1029,12 @@ void BattleAICmd_score(void) gAIScriptPtr += 2; // AI return. } -void BattleAICmd_if_hp_less_than(void) +static void BattleAICmd_if_hp_less_than(void) { u16 index; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -942,12 +1044,12 @@ void BattleAICmd_if_hp_less_than(void) gAIScriptPtr += 7; } -void BattleAICmd_if_hp_more_than(void) +static void BattleAICmd_if_hp_more_than(void) { u16 index; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -957,12 +1059,12 @@ void BattleAICmd_if_hp_more_than(void) gAIScriptPtr += 7; } -void BattleAICmd_if_hp_equal(void) +static void BattleAICmd_if_hp_equal(void) { u16 index; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -972,12 +1074,12 @@ void BattleAICmd_if_hp_equal(void) gAIScriptPtr += 7; } -void BattleAICmd_if_hp_not_equal(void) +static void BattleAICmd_if_hp_not_equal(void) { u16 index; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -987,13 +1089,13 @@ void BattleAICmd_if_hp_not_equal(void) gAIScriptPtr += 7; } -void BattleAICmd_if_status(void) +static void BattleAICmd_if_status(void) { u16 index; u32 arg; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1005,13 +1107,13 @@ void BattleAICmd_if_status(void) gAIScriptPtr += 10; } -void BattleAICmd_if_not_status(void) +static void BattleAICmd_if_not_status(void) { u16 index; u32 arg; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1023,13 +1125,13 @@ void BattleAICmd_if_not_status(void) gAIScriptPtr += 10; } -void BattleAICmd_if_status2(void) +static void BattleAICmd_if_status2(void) { u16 index; u32 arg; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1041,13 +1143,13 @@ void BattleAICmd_if_status2(void) gAIScriptPtr += 10; } -void BattleAICmd_if_not_status2(void) +static void BattleAICmd_if_not_status2(void) { u16 index; u32 arg; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1059,13 +1161,13 @@ void BattleAICmd_if_not_status2(void) gAIScriptPtr += 10; } -void BattleAICmd_if_status3(void) +static void BattleAICmd_if_status3(void) { u16 index; u32 arg; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1077,13 +1179,13 @@ void BattleAICmd_if_status3(void) gAIScriptPtr += 10; } -void BattleAICmd_if_not_status3(void) +static void BattleAICmd_if_not_status3(void) { u16 index; u32 arg; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1095,45 +1197,45 @@ void BattleAICmd_if_not_status3(void) gAIScriptPtr += 10; } -void BattleAICmd_if_status4(void) +static void BattleAICmd_if_side_affecting(void) { u16 index; u32 arg1, arg2; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; arg1 = GetBankIdentity(index) & 1; arg2 = AIScriptRead32(gAIScriptPtr + 2); - if ((gUnknown_0202428E[arg1] & arg2) != 0) + if ((gSideAffecting[arg1] & arg2) != 0) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); else gAIScriptPtr += 10; } -void BattleAICmd_if_not_status4(void) +static void BattleAICmd_if_not_side_affecting(void) { u16 index; u32 arg1, arg2; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; arg1 = GetBankIdentity(index) & 1; arg2 = AIScriptRead32(gAIScriptPtr + 2); - if ((gUnknown_0202428E[arg1] & arg2) == 0) + if ((gSideAffecting[arg1] & arg2) == 0) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); else gAIScriptPtr += 10; } -void BattleAICmd_if_less_than(void) +static void BattleAICmd_if_less_than(void) { if (AI_THINKING_STRUCT->funcResult < gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -1141,7 +1243,7 @@ void BattleAICmd_if_less_than(void) gAIScriptPtr += 6; } -void BattleAICmd_if_more_than(void) +static void BattleAICmd_if_more_than(void) { if (AI_THINKING_STRUCT->funcResult > gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -1149,7 +1251,7 @@ void BattleAICmd_if_more_than(void) gAIScriptPtr += 6; } -void BattleAICmd_if_equal(void) +static void BattleAICmd_if_equal(void) { if (AI_THINKING_STRUCT->funcResult == gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -1157,7 +1259,7 @@ void BattleAICmd_if_equal(void) gAIScriptPtr += 6; } -void BattleAICmd_if_not_equal(void) +static void BattleAICmd_if_not_equal(void) { if (AI_THINKING_STRUCT->funcResult != gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -1165,7 +1267,7 @@ void BattleAICmd_if_not_equal(void) gAIScriptPtr += 6; } -void BattleAICmd_if_less_than_32(void) +static void BattleAICmd_if_less_than_32(void) { u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); @@ -1175,7 +1277,7 @@ void BattleAICmd_if_less_than_32(void) gAIScriptPtr += 9; } -void BattleAICmd_if_more_than_32(void) +static void BattleAICmd_if_more_than_32(void) { u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); @@ -1185,7 +1287,7 @@ void BattleAICmd_if_more_than_32(void) gAIScriptPtr += 9; } -void BattleAICmd_if_equal_32(void) +static void BattleAICmd_if_equal_32(void) { u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); @@ -1195,7 +1297,7 @@ void BattleAICmd_if_equal_32(void) gAIScriptPtr += 9; } -void BattleAICmd_if_not_equal_32(void) +static void BattleAICmd_if_not_equal_32(void) { u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); @@ -1205,7 +1307,7 @@ void BattleAICmd_if_not_equal_32(void) gAIScriptPtr += 9; } -void BattleAICmd_if_move(void) +static void BattleAICmd_if_move(void) { u16 move = AIScriptRead16(gAIScriptPtr + 1); @@ -1215,7 +1317,7 @@ void BattleAICmd_if_move(void) gAIScriptPtr += 7; } -void BattleAICmd_if_not_move(void) +static void BattleAICmd_if_not_move(void) { u16 move = AIScriptRead16(gAIScriptPtr + 1); @@ -1225,7 +1327,7 @@ void BattleAICmd_if_not_move(void) gAIScriptPtr += 7; } -void BattleAICmd_if_in_bytes(void) +static void BattleAICmd_if_in_bytes(void) { u8 *ptr = AIScriptReadPtr(gAIScriptPtr + 1); @@ -1241,7 +1343,7 @@ void BattleAICmd_if_in_bytes(void) gAIScriptPtr += 9; } -void BattleAICmd_if_not_in_bytes(void) +static void BattleAICmd_if_not_in_bytes(void) { u8 *ptr = AIScriptReadPtr(gAIScriptPtr + 1); @@ -1257,7 +1359,7 @@ void BattleAICmd_if_not_in_bytes(void) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); } -void BattleAICmd_if_in_words(void) +static void BattleAICmd_if_in_words(void) { u16 *ptr = (u16 *)AIScriptReadPtr(gAIScriptPtr + 1); @@ -1273,7 +1375,7 @@ void BattleAICmd_if_in_words(void) gAIScriptPtr += 9; } -void BattleAICmd_if_not_in_words(void) +static void BattleAICmd_if_not_in_words(void) { u16 *ptr = (u16 *)AIScriptReadPtr(gAIScriptPtr + 1); @@ -1289,14 +1391,14 @@ void BattleAICmd_if_not_in_words(void) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); } -void BattleAICmd_if_user_can_damage(void) +static void BattleAICmd_if_user_can_damage(void) { s32 i; for (i = 0; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex].moves[i] != 0 - && gBattleMoves[gBattleMons[gPlayerMonIndex].moves[i]].power != 0) + if (gBattleMons[sBank_AI].moves[i] != 0 + && gBattleMoves[gBattleMons[sBank_AI].moves[i]].power != 0) break; } if (i == 4) @@ -1305,14 +1407,14 @@ void BattleAICmd_if_user_can_damage(void) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); } -void BattleAICmd_if_user_cant_damage(void) +static void BattleAICmd_if_user_cant_damage(void) { s32 i; for (i = 0; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex].moves[i] != 0 - && gBattleMoves[gBattleMons[gPlayerMonIndex].moves[i]].power != 0) + if (gBattleMons[sBank_AI].moves[i] != 0 + && gBattleMoves[gBattleMons[sBank_AI].moves[i]].power != 0) break; } if (i != 4) @@ -1321,26 +1423,26 @@ void BattleAICmd_if_user_cant_damage(void) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); } -void BattleAICmd_get_turn_count(void) +static void BattleAICmd_get_turn_count(void) { - AI_THINKING_STRUCT->funcResult = gUnknown_03005D10[19]; + AI_THINKING_STRUCT->funcResult = gBattleResults.battleTurnCounter; gAIScriptPtr += 1; } -void BattleAICmd_get_type(void) +static void BattleAICmd_get_type(void) { u8 typeVar = gAIScriptPtr[1]; switch (typeVar) { case 1: // player primary type - AI_THINKING_STRUCT->funcResult = gBattleMons[gPlayerMonIndex].type1; + AI_THINKING_STRUCT->funcResult = gBattleMons[sBank_AI].type1; break; case 0: // enemy primary type AI_THINKING_STRUCT->funcResult = gBattleMons[gBankTarget].type1; break; case 3: // player secondary type - AI_THINKING_STRUCT->funcResult = gBattleMons[gPlayerMonIndex].type2; + AI_THINKING_STRUCT->funcResult = gBattleMons[sBank_AI].type2; break; case 2: // enemy secondary type AI_THINKING_STRUCT->funcResult = gBattleMons[gBankTarget].type2; @@ -1352,28 +1454,27 @@ void BattleAICmd_get_type(void) gAIScriptPtr += 2; } -// util for double battles? whats this doing in the middle of the battle AI macros? -u8 sub_8131E70(u8 index) +static u8 BattleAI_GetWantedBank(u8 index) { switch (index) { - case 1: - return gPlayerMonIndex; - case 0: + case AI_USER: + return sBank_AI; + case AI_TARGET: default: return gBankTarget; - case 3: - return gPlayerMonIndex ^ 2; - case 2: + case AI_USER_PARTNER: + return sBank_AI ^ 2; + case AI_TARGET_PARTNER: return gBankTarget ^ 2; } } -void BattleAICmd_unk_5F(void) +static void BattleAICmd_is_of_type(void) { - u8 index = sub_8131E70(gAIScriptPtr[1]); - - if(gBattleMons[index].type1 == gAIScriptPtr[2] || gBattleMons[index].type2 == gAIScriptPtr[2]) + u8 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); + + if(gBattleMons[bank].type1 == gAIScriptPtr[2] || gBattleMons[bank].type2 == gAIScriptPtr[2]) { AI_THINKING_STRUCT->funcResult = 1; } @@ -1385,14 +1486,14 @@ void BattleAICmd_unk_5F(void) gAIScriptPtr += 3; } -void BattleAICmd_get_move_power(void) +static void BattleAICmd_get_last_used_bank_move_power(void) { AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power; gAIScriptPtr += 1; } __attribute__((naked)) // not even going to try. if it doesnt match in ruby, it wont match in emerald (yet). -void BattleAICmd_is_most_powerful_move(void) +static void BattleAICmd_is_most_powerful_move(void) { asm(".syntax unified\n\ push {r4-r7,lr}\n\ @@ -1402,7 +1503,7 @@ void BattleAICmd_is_most_powerful_move(void) push {r5-r7}\n\ sub sp, 0x14\n\ movs r3, 0\n\ - ldr r0, =gUnknown_085B09C8\n\ + ldr r0, =sDiscouragedPowerfulMoveEffects\n\ ldrh r1, [r0]\n\ ldr r5, =0x0000ffff\n\ ldr r6, =gBattleMoves\n\ @@ -1417,7 +1518,7 @@ void BattleAICmd_is_most_powerful_move(void) lsls r0, 2\n\ adds r0, r6\n\ ldrb r4, [r0]\n\ - ldr r1, =gUnknown_085B09C8\n\ + ldr r1, =sDiscouragedPowerfulMoveEffects\n\ _08131F76:\n\ ldrh r0, [r1]\n\ cmp r4, r0\n\ @@ -1441,7 +1542,7 @@ _08131F86:\n\ b _08132126\n\ _08131F9C:\n\ lsls r0, r3, 1\n\ - ldr r1, =gUnknown_085B09C8\n\ + ldr r1, =sDiscouragedPowerfulMoveEffects\n\ adds r0, r1\n\ ldrh r3, [r0]\n\ ldr r0, =0x0000ffff\n\ @@ -1449,7 +1550,7 @@ _08131F9C:\n\ beq _08131FAC\n\ b _08132126\n\ _08131FAC:\n\ - ldr r0, =gUnknown_02024400\n\ + ldr r0, =gDynamicBasePower\n\ movs r1, 0\n\ strh r1, [r0]\n\ ldr r0, =gBattleStruct\n\ @@ -1464,14 +1565,14 @@ _08131FAC:\n\ strb r2, [r0]\n\ movs r6, 0\n\ mov r9, r3\n\ - ldr r2, =gUnknown_085B09C8\n\ + ldr r2, =sDiscouragedPowerfulMoveEffects\n\ ldrh r2, [r2]\n\ str r2, [sp, 0x10]\n\ _08131FD0:\n\ movs r3, 0\n\ ldr r5, =gBattleMons\n\ lsls r4, r6, 1\n\ - ldr r7, =gPlayerMonIndex\n\ + ldr r7, =sBank_AI\n\ lsls r0, r6, 2\n\ mov r8, r0\n\ adds r1, r6, 0x1\n\ @@ -1493,7 +1594,7 @@ _08131FD0:\n\ lsls r0, 2\n\ adds r0, r2\n\ ldrb r2, [r0]\n\ - ldr r1, =gUnknown_085B09C8\n\ + ldr r1, =sDiscouragedPowerfulMoveEffects\n\ _08132004:\n\ ldrh r0, [r1]\n\ cmp r2, r0\n\ @@ -1515,7 +1616,7 @@ _08132014:\n\ cmp r0, 0\n\ beq _081320C0\n\ lsls r0, r3, 1\n\ - ldr r2, =gUnknown_085B09C8\n\ + ldr r2, =sDiscouragedPowerfulMoveEffects\n\ adds r0, r2\n\ ldrh r0, [r0]\n\ cmp r0, r9\n\ @@ -1534,11 +1635,11 @@ _08132014:\n\ ldrb r0, [r7]\n\ ldr r4, =gBankTarget\n\ ldrb r1, [r4]\n\ - bl sub_8046E7C\n\ + bl AI_CalcDmg\n\ ldrh r0, [r5]\n\ ldrb r1, [r7]\n\ ldrb r2, [r4]\n\ - bl move_effectiveness_something\n\ + bl TypeCalc\n\ mov r4, sp\n\ add r4, r8\n\ ldr r2, =gBattleMoveDamage\n\ @@ -1635,17 +1736,17 @@ _08132130:\n\ .syntax divided"); } -void BattleAICmd_get_move(void) +static void BattleAICmd_get_last_used_bank_move(void) { - if (gAIScriptPtr[1] == USER) - AI_THINKING_STRUCT->funcResult = gUnknown_02024248[gPlayerMonIndex]; + if (gAIScriptPtr[1] == AI_USER) + AI_THINKING_STRUCT->funcResult = gLastUsedMovesByBanks[sBank_AI]; else - AI_THINKING_STRUCT->funcResult = gUnknown_02024248[gBankTarget]; + AI_THINKING_STRUCT->funcResult = gLastUsedMovesByBanks[gBankTarget]; gAIScriptPtr += 2; } -void BattleAICmd_if_arg_equal(void) +static void BattleAICmd_if_arg_equal(void) { if (gAIScriptPtr[1] == AI_THINKING_STRUCT->funcResult) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -1653,7 +1754,7 @@ void BattleAICmd_if_arg_equal(void) gAIScriptPtr += 6; } -void BattleAICmd_if_arg_not_equal(void) +static void BattleAICmd_if_arg_not_equal(void) { if (gAIScriptPtr[1] != AI_THINKING_STRUCT->funcResult) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -1661,41 +1762,41 @@ void BattleAICmd_if_arg_not_equal(void) gAIScriptPtr += 6; } -void BattleAICmd_if_would_go_first(void) +static void BattleAICmd_if_would_go_first(void) { - if (b_first_side(gPlayerMonIndex, gBankTarget, 1) == gAIScriptPtr[1]) + if (b_first_side(sBank_AI, gBankTarget, 1) == gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); else gAIScriptPtr += 6; } -void BattleAICmd_if_would_not_go_first(void) +static void BattleAICmd_if_would_not_go_first(void) { - if (b_first_side(gPlayerMonIndex, gBankTarget, 1) != gAIScriptPtr[1]) + if (b_first_side(sBank_AI, gBankTarget, 1) != gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); else gAIScriptPtr += 6; } -void BattleAICmd_nullsub_2A(void) +static void BattleAICmd_nullsub_2A(void) { } -void BattleAICmd_nullsub_2B(void) +static void BattleAICmd_nullsub_2B(void) { } -void BattleAICmd_count_alive_pokemon(void) +static void BattleAICmd_count_alive_pokemon(void) { u8 index; - u8 var, var2; + u8 bankOnField1, bankOnField2; struct Pokemon *party; int i; AI_THINKING_STRUCT->funcResult = 0; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; @@ -1707,19 +1808,19 @@ void BattleAICmd_count_alive_pokemon(void) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { u32 status; - var = gBattlePartyID[index][0]; + bankOnField1 = gBattlePartyID[index]; status = GetBankIdentity(index) ^ 2; - var2 = gBattlePartyID[GetBankByPlayerAI(status)][0]; + bankOnField2 = gBattlePartyID[GetBankByPlayerAI(status)]; } - else + else // in singles there's only one bank by side { - var = gBattlePartyID[index][0]; - var2 = gBattlePartyID[index][0]; + bankOnField1 = gBattlePartyID[index]; + bankOnField2 = gBattlePartyID[index]; } for (i = 0; i < 6; i++) { - if (i != var && i != var2 + if (i != bankOnField1 && i != bankOnField2 && GetMonData(&party[i], MON_DATA_HP) != 0 && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG) @@ -1731,39 +1832,39 @@ void BattleAICmd_count_alive_pokemon(void) gAIScriptPtr += 2; } -void BattleAICmd_get_considered_move(void) +static void BattleAICmd_get_considered_move(void) { AI_THINKING_STRUCT->funcResult = AI_THINKING_STRUCT->moveConsidered; gAIScriptPtr += 1; } -void BattleAICmd_get_considered_move_effect(void) +static void BattleAICmd_get_considered_move_effect(void) { AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect; gAIScriptPtr += 1; } -void BattleAICmd_get_ability(void) +static void BattleAICmd_get_ability(void) { u8 index; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + index = sBank_AI; else index = gBankTarget; if(gActiveBank != index) { - if(UNK_2016A00_STRUCT->unk40[index] != 0) + if(BATTLE_HISTORY->abilities[index] != 0) { - AI_THINKING_STRUCT->funcResult = UNK_2016A00_STRUCT->unk40[index]; + AI_THINKING_STRUCT->funcResult = BATTLE_HISTORY->abilities[index]; gAIScriptPtr += 2; return; } - + // abilities that prevent fleeing. - if (gBattleMons[index].ability == ABILITY_SHADOW_TAG - || gBattleMons[index].ability == ABILITY_MAGNET_PULL + if (gBattleMons[index].ability == ABILITY_SHADOW_TAG + || gBattleMons[index].ability == ABILITY_MAGNET_PULL || gBattleMons[index].ability == ABILITY_ARENA_TRAP) { AI_THINKING_STRUCT->funcResult = gBattleMons[index].ability; @@ -1776,7 +1877,7 @@ void BattleAICmd_get_ability(void) if (gBaseStats[gBattleMons[index].species].ability2 != ABILITY_NONE) { // AI has no knowledge of opponent, so it guesses which ability. - if(Random() & 1) + if (Random() & 1) { AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability1; } @@ -1784,7 +1885,7 @@ void BattleAICmd_get_ability(void) { AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability2; } - } + } else { AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability1; // it's definitely ability 1. @@ -1804,90 +1905,76 @@ void BattleAICmd_get_ability(void) } #ifdef NONMATCHING -void tai60_unk(void) +static void BattleAICmd_check_ability(void) { - u8 index = sub_8131E70(gAIScriptPtr[1]); - u8 arg2 = gAIScriptPtr[2]; - u8 var; - - if(gAIScriptPtr[1] == 0 || gAIScriptPtr[1] == 2) + u8 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); + u8 ability = gAIScriptPtr[2]; + + if (gAIScriptPtr[1] == AI_TARGET || gAIScriptPtr[1] == AI_TARGET_PARTNER) { - // _0813253A - if(UNK_2016A00_STRUCT->unk40[index] != 0) + if (BATTLE_HISTORY->abilities[bank] != 0) { - var = UNK_2016A00_STRUCT->unk40[index]; - AI_THINKING_STRUCT->funcResult = var; + ability = BATTLE_HISTORY->abilities[bank]; + AI_THINKING_STRUCT->funcResult = ability; } - else + // abilities that prevent fleeing. + else if (gBattleMons[bank].ability == ABILITY_SHADOW_TAG + || gBattleMons[bank].ability == ABILITY_MAGNET_PULL + || gBattleMons[bank].ability == ABILITY_ARENA_TRAP) { - // _0813255C - if (gBattleMons[index].ability == ABILITY_SHADOW_TAG - || gBattleMons[index].ability == ABILITY_MAGNET_PULL - || gBattleMons[index].ability == ABILITY_ARENA_TRAP) - { - var = gBattleMons[index].ability; - } - else + ability = gBattleMons[bank].ability; + } + else if (gBaseStats[gBattleMons[bank].species].ability1 != ABILITY_NONE) + { + if (gBaseStats[gBattleMons[bank].species].ability2 != ABILITY_NONE) { - // _08132588 - if (gBaseStats[gBattleMons[index].species].ability1 != ABILITY_NONE) + if (gBaseStats[gBattleMons[bank].species].ability1 != ability + && gBaseStats[gBattleMons[bank].species].ability2 != ability) { - if (gBaseStats[gBattleMons[index].species].ability2 != ABILITY_NONE) - { - if(gBaseStats[gBattleMons[index].species].ability1 != arg2 && gBaseStats[gBattleMons[index].species].ability2 != arg2) - { - var = 2; - } - else - { - var = gBaseStats[gBattleMons[index].species].ability1; - } - } - else - { - // _081325B4 - var = gBaseStats[gBattleMons[index].species].ability1; - } + ability = gBaseStats[gBattleMons[bank].species].ability1; } else - { - // _081325B8 - var = gBaseStats[gBattleMons[index].species].ability2; - } + ability = 0; + } + else + { + ability = gBaseStats[gBattleMons[bank].species].ability1; } } + else + { + ability = gBaseStats[gBattleMons[bank].species].ability2; // AI cant actually reach this part since every mon has at least 1 ability. + } } else { - // _081325BC - var = gBattleMons[index].ability; + // The AI knows its own or partner's ability. + ability = gBattleMons[bank].ability; } - - // _081325CA - if(var == ABILITY_NONE) + if (ability == 0) { - AI_THINKING_STRUCT->funcResult = 2; + AI_THINKING_STRUCT->funcResult = 2; // unable to answer } - else if(var == arg2) + else if (ability == gAIScriptPtr[2]) { - AI_THINKING_STRUCT->funcResult = 1; + AI_THINKING_STRUCT->funcResult = 1; // pokemon has the ability we wanted to check } else { - AI_THINKING_STRUCT->funcResult = 0; + AI_THINKING_STRUCT->funcResult = 0; // pokemon doesn't have the ability we wanted to check } gAIScriptPtr += 3; } #else __attribute__((naked)) -void tai60_unk(void) +static void BattleAICmd_check_ability(void) { asm(".syntax unified\n\ push {r4-r6,lr}\n\ ldr r4, =gAIScriptPtr\n\ ldr r0, [r4]\n\ ldrb r0, [r0, 0x1]\n\ - bl sub_8131E70\n\ + bl BattleAI_GetWantedBank\n\ lsls r0, 24\n\ lsrs r5, r0, 24\n\ ldr r0, [r4]\n\ @@ -2010,13 +2097,15 @@ _08132608:\n\ } #endif -void BattleAICmd_get_highest_possible_damage(void) +static void BattleAICmd_get_highest_type_effectiveness(void) { s32 i; + u8* dynamicMoveType; - gUnknown_02024400 = 0; - gBattleStruct[0x13] = 0; - gBattleScripting[0xE] = 1; + gDynamicBasePower = 0; + dynamicMoveType = &gBattleStruct->dynamicMoveType; + *dynamicMoveType = 0; + gBattleScripting.dmgMultiplier = 1; gBattleMoveFlags = 0; gCritMultiplier = 1; AI_THINKING_STRUCT->funcResult = 0; @@ -2024,11 +2113,11 @@ void BattleAICmd_get_highest_possible_damage(void) for (i = 0; i < 4; i++) { gBattleMoveDamage = 40; - gCurrentMove = gBattleMons[gPlayerMonIndex].moves[i]; + gCurrentMove = gBattleMons[sBank_AI].moves[i]; if (gCurrentMove) { - move_effectiveness_something(gCurrentMove, gPlayerMonIndex, gBankTarget); + TypeCalc(gCurrentMove, sBank_AI, gBankTarget); // reduce by 1/3. if (gBattleMoveDamage == 120) @@ -2040,7 +2129,7 @@ void BattleAICmd_get_highest_possible_damage(void) if (gBattleMoveDamage == 15) gBattleMoveDamage = 10; - if (gBattleMoveFlags & 8) // if it's a status move, it wont do anything. + if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) gBattleMoveDamage = 0; if (AI_THINKING_STRUCT->funcResult < gBattleMoveDamage) @@ -2050,20 +2139,20 @@ void BattleAICmd_get_highest_possible_damage(void) gAIScriptPtr += 1; } -void BattleAICmd_if_damage_bonus(void) +static void BattleAICmd_if_type_effectiveness(void) { u8 damageVar; - gUnknown_02024400 = 0; - gBattleStruct[0x13] = 0; - gBattleScripting[0xE] = 1; + gDynamicBasePower = 0; + gBattleStruct->dynamicMoveType = 0; + gBattleScripting.dmgMultiplier = 1; gBattleMoveFlags = 0; gCritMultiplier = 1; gBattleMoveDamage = 40; gCurrentMove = AI_THINKING_STRUCT->moveConsidered; - move_effectiveness_something(gCurrentMove, gPlayerMonIndex, gBankTarget); + TypeCalc(gCurrentMove, sBank_AI, gBankTarget); if (gBattleMoveDamage == 120) gBattleMoveDamage = 80; @@ -2074,7 +2163,7 @@ void BattleAICmd_if_damage_bonus(void) if (gBattleMoveDamage == 15) gBattleMoveDamage = 10; - if (gBattleMoveFlags & 8) + if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) gBattleMoveDamage = 0; // store gBattleMoveDamage in a u8 variable because gAIScriptPtr[1] is a u8. @@ -2086,15 +2175,15 @@ void BattleAICmd_if_damage_bonus(void) gAIScriptPtr += 6; } -void BattleAICmd_nullsub_32(void) +static void BattleAICmd_nullsub_32(void) { } -void BattleAICmd_nullsub_33(void) +static void BattleAICmd_nullsub_33(void) { } -void BattleAICmd_if_status_in_party(void) +static void BattleAICmd_if_status_in_party(void) { struct Pokemon *party; int i; @@ -2104,7 +2193,7 @@ void BattleAICmd_if_status_in_party(void) switch(gAIScriptPtr[1]) { case 1: - index = gPlayerMonIndex; + index = sBank_AI; break; default: index = gBankTarget; @@ -2131,7 +2220,7 @@ void BattleAICmd_if_status_in_party(void) gAIScriptPtr += 10; } -void BattleAICmd_if_status_not_in_party(void) +static void BattleAICmd_if_status_not_in_party(void) { struct Pokemon *party; int i; @@ -2141,7 +2230,7 @@ void BattleAICmd_if_status_not_in_party(void) switch(gAIScriptPtr[1]) { case 1: - index = gPlayerMonIndex; + index = sBank_AI; break; default: index = gBankTarget; @@ -2167,21 +2256,21 @@ void BattleAICmd_if_status_not_in_party(void) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); } -void BattleAICmd_get_weather(void) +static void BattleAICmd_get_weather(void) { - if (gBattleWeather & 7) + if (gBattleWeather & WEATHER_RAIN_ANY) AI_THINKING_STRUCT->funcResult = 1; - if (gBattleWeather & 0x18) + if (gBattleWeather & WEATHER_SANDSTORM_ANY) AI_THINKING_STRUCT->funcResult = 2; - if (gBattleWeather & 0x60) + if (gBattleWeather & WEATHER_SUN_ANY) AI_THINKING_STRUCT->funcResult = 0; - if (gBattleWeather & 0x80) + if (gBattleWeather & WEATHER_HAIL_ANY) AI_THINKING_STRUCT->funcResult = 3; gAIScriptPtr += 1; } -void BattleAICmd_if_effect(void) +static void BattleAICmd_if_effect(void) { if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect == gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -2189,7 +2278,7 @@ void BattleAICmd_if_effect(void) gAIScriptPtr += 6; } -void BattleAICmd_if_not_effect(void) +static void BattleAICmd_if_not_effect(void) { if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect != gAIScriptPtr[1]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); @@ -2197,67 +2286,67 @@ void BattleAICmd_if_not_effect(void) gAIScriptPtr += 6; } -void BattleAICmd_if_stat_level_less_than(void) +static void BattleAICmd_if_stat_level_less_than(void) { - u32 party; + u32 bank; - if (gAIScriptPtr[1] == USER) - party = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - party = gBankTarget; + bank = gBankTarget; - if (gBattleMons[party].statStages[gAIScriptPtr[2]] < gAIScriptPtr[3]) + if (gBattleMons[bank].statStages[gAIScriptPtr[2]] < gAIScriptPtr[3]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); else gAIScriptPtr += 8; } -void BattleAICmd_if_stat_level_more_than(void) +static void BattleAICmd_if_stat_level_more_than(void) { - u32 party; + u32 bank; - if (gAIScriptPtr[1] == USER) - party = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - party = gBankTarget; + bank = gBankTarget; - if (gBattleMons[party].statStages[gAIScriptPtr[2]] > gAIScriptPtr[3]) + if (gBattleMons[bank].statStages[gAIScriptPtr[2]] > gAIScriptPtr[3]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); else gAIScriptPtr += 8; } -void BattleAICmd_if_stat_level_equal(void) +static void BattleAICmd_if_stat_level_equal(void) { - u32 party; + u32 bank; - if (gAIScriptPtr[1] == USER) - party = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - party = gBankTarget; + bank = gBankTarget; - if (gBattleMons[party].statStages[gAIScriptPtr[2]] == gAIScriptPtr[3]) + if (gBattleMons[bank].statStages[gAIScriptPtr[2]] == gAIScriptPtr[3]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); else gAIScriptPtr += 8; } -void BattleAICmd_if_stat_level_not_equal(void) +static void BattleAICmd_if_stat_level_not_equal(void) { - u32 party; + u32 bank; - if (gAIScriptPtr[1] == USER) - party = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - party = gBankTarget; + bank = gBankTarget; - if (gBattleMons[party].statStages[gAIScriptPtr[2]] != gAIScriptPtr[3]) + if (gBattleMons[bank].statStages[gAIScriptPtr[2]] != gAIScriptPtr[3]) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); else gAIScriptPtr += 8; } -void BattleAICmd_if_can_faint(void) +static void BattleAICmd_if_can_faint(void) { if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power < 2) { @@ -2265,16 +2354,16 @@ void BattleAICmd_if_can_faint(void) return; } - gUnknown_02024400 = 0; - gBattleStruct[0x13] = 0; - gBattleScripting[0xE] = 1; + gDynamicBasePower = 0; + gBattleStruct->dynamicMoveType = 0; + gBattleScripting.dmgMultiplier = 1; gBattleMoveFlags = 0; gCritMultiplier = 1; gCurrentMove = AI_THINKING_STRUCT->moveConsidered; - sub_8046E7C(gPlayerMonIndex, gBankTarget); - move_effectiveness_something(gCurrentMove, gPlayerMonIndex, gBankTarget); + AI_CalcDmg(sBank_AI, gBankTarget); + TypeCalc(gCurrentMove, sBank_AI, gBankTarget); - gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->unk18[AI_THINKING_STRUCT->movesetIndex] / 100; + gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[AI_THINKING_STRUCT->movesetIndex] / 100; // moves always do at least 1 damage. if (gBattleMoveDamage == 0) @@ -2286,7 +2375,7 @@ void BattleAICmd_if_can_faint(void) gAIScriptPtr += 5; } -void BattleAICmd_if_cant_faint(void) +static void BattleAICmd_if_cant_faint(void) { if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power < 2) { @@ -2294,16 +2383,16 @@ void BattleAICmd_if_cant_faint(void) return; } - gUnknown_02024400 = 0; - gBattleStruct[0x13] = 0; - gBattleScripting[0xE] = 1; + gDynamicBasePower = 0; + gBattleStruct->dynamicMoveType = 0; + gBattleScripting.dmgMultiplier = 1; gBattleMoveFlags = 0; gCritMultiplier = 1; gCurrentMove = AI_THINKING_STRUCT->moveConsidered; - sub_8046E7C(gPlayerMonIndex, gBankTarget); - move_effectiveness_something(gCurrentMove, gPlayerMonIndex, gBankTarget); + AI_CalcDmg(sBank_AI, gBankTarget); + TypeCalc(gCurrentMove, sBank_AI, gBankTarget); - gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->unk18[AI_THINKING_STRUCT->movesetIndex] / 100; + gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[AI_THINKING_STRUCT->movesetIndex] / 100; // this macro is missing the damage 0 = 1 assumption. @@ -2313,18 +2402,17 @@ void BattleAICmd_if_cant_faint(void) gAIScriptPtr += 5; } -void BattleAICmd_if_has_move(void) +static void BattleAICmd_if_has_move(void) { int i; u16 *temp_ptr = (u16 *)(gAIScriptPtr + 2); - + switch(gAIScriptPtr[1]) { - case 1: - // _08132E42 + case AI_USER: for (i = 0; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex].moves[i] == *temp_ptr) + if (gBattleMons[sBank_AI].moves[i] == *temp_ptr) break; } if (i == 4) @@ -2336,9 +2424,9 @@ void BattleAICmd_if_has_move(void) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); return; - } - case 3: // new to Emerald - if(gBattleMons[gPlayerMonIndex ^ 2].hp == 0) + } + case AI_USER_PARTNER: + if (gBattleMons[sBank_AI ^ 2].hp == 0) { gAIScriptPtr += 8; return; @@ -2347,7 +2435,7 @@ void BattleAICmd_if_has_move(void) { for (i = 0; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex ^ 2].moves[i] == *temp_ptr) + if (gBattleMons[sBank_AI ^ 2].moves[i] == *temp_ptr) break; } } @@ -2360,12 +2448,12 @@ void BattleAICmd_if_has_move(void) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); return; - } - case 0: - case 2: + } + case AI_TARGET: + case AI_TARGET_PARTNER: for (i = 0; i < 4; i++) { - if (UNK_2016A00_STRUCT->unk0[gBankTarget][i] == *temp_ptr) + if (BATTLE_HISTORY->usedMoves[gBankTarget].moves[i] == *temp_ptr) break; } if (i == 4) @@ -2381,18 +2469,18 @@ void BattleAICmd_if_has_move(void) } } -void BattleAICmd_if_dont_have_move(void) +static void BattleAICmd_if_dont_have_move(void) { int i; u16 *temp_ptr = (u16 *)(gAIScriptPtr + 2); - + switch(gAIScriptPtr[1]) { - case 1: - case 3: // if_dont_have_move does not have the seperate 3 case check in Emerald unlike if_has_move. + case AI_USER: + case AI_USER_PARTNER: // UB: no separate check for user partner for (i = 0; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex].moves[i] == *temp_ptr) + if (gBattleMons[sBank_AI].moves[i] == *temp_ptr) break; } if (i != 4) @@ -2405,11 +2493,11 @@ void BattleAICmd_if_dont_have_move(void) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); return; } - case 0: - case 2: + case AI_TARGET: + case AI_TARGET_PARTNER: for (i = 0; i < 4; i++) { - if (UNK_2016A00_STRUCT->unk0[gBankTarget][i] == *temp_ptr) + if (BATTLE_HISTORY->usedMoves[gBankTarget].moves[i] == *temp_ptr) break; } if (i != 4) @@ -2425,17 +2513,17 @@ void BattleAICmd_if_dont_have_move(void) } } -void BattleAICmd_if_move_effect(void) +static void BattleAICmd_if_move_effect(void) { int i; switch (gAIScriptPtr[1]) { - case 1: - case 3: // _08133044 - for(i = 0; i < 4; i++) + case AI_USER: + case AI_USER_PARTNER: + for (i = 0; i < 4; i++) { - if(gBattleMons[gPlayerMonIndex].moves[i] != 0 && gBattleMoves[gBattleMons[gPlayerMonIndex].moves[i]].effect == gAIScriptPtr[2]) + if(gBattleMons[sBank_AI].moves[i] != 0 && gBattleMoves[gBattleMons[sBank_AI].moves[i]].effect == gAIScriptPtr[2]) break; } if (i == 4) @@ -2443,11 +2531,11 @@ void BattleAICmd_if_move_effect(void) else gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); break; - case 0: - case 2: // _08133090 + case AI_TARGET: + case AI_TARGET_PARTNER: for (i = 0; i < 4; i++) { - if (gBattleMons[gPlayerMonIndex].moves[i] != 0 && gBattleMoves[UNK_2016A00_STRUCT->unk0[gBankTarget][i]].effect == gAIScriptPtr[2]) + if (gBattleMons[sBank_AI].moves[i] != 0 && gBattleMoves[BATTLE_HISTORY->usedMoves[gBankTarget].moves[i]].effect == gAIScriptPtr[2]) break; } if (i == 4) @@ -2458,17 +2546,17 @@ void BattleAICmd_if_move_effect(void) } } -void BattleAICmd_if_not_move_effect(void) +static void BattleAICmd_if_not_move_effect(void) { int i; switch (gAIScriptPtr[1]) { - case 1: - case 3: // _0813313C - for(i = 0; i < 4; i++) + case AI_USER: + case AI_USER_PARTNER: + for (i = 0; i < 4; i++) { - if(gBattleMons[gPlayerMonIndex].moves[i] != 0 && gBattleMoves[gBattleMons[gPlayerMonIndex].moves[i]].effect == gAIScriptPtr[2]) + if(gBattleMons[sBank_AI].moves[i] != 0 && gBattleMoves[gBattleMons[sBank_AI].moves[i]].effect == gAIScriptPtr[2]) break; } if (i != 4) @@ -2476,11 +2564,11 @@ void BattleAICmd_if_not_move_effect(void) else gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); break; - case 0: - case 2: // _08133188 + case AI_TARGET: + case AI_TARGET_PARTNER: for (i = 0; i < 4; i++) { - if (UNK_2016A00_STRUCT->unk0[gBankTarget][i] && gBattleMoves[UNK_2016A00_STRUCT->unk0[gBankTarget][i]].effect == gAIScriptPtr[2]) + if (BATTLE_HISTORY->usedMoves[gBankTarget].moves[i] && gBattleMoves[BATTLE_HISTORY->usedMoves[gBankTarget].moves[i]].effect == gAIScriptPtr[2]) break; } if (i != 4) @@ -2491,18 +2579,18 @@ void BattleAICmd_if_not_move_effect(void) } } -void BattleAICmd_if_last_move_did_damage(void) +static void BattleAICmd_if_any_move_disabled_or_encored(void) { - u8 index; + u8 bank; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; if (gAIScriptPtr[2] == 0) { - if (gDisableStructs[index].unk4 == 0) + if (gDisableStructs[bank].disabledMove == 0) { gAIScriptPtr += 7; return; @@ -2515,7 +2603,7 @@ void BattleAICmd_if_last_move_did_damage(void) gAIScriptPtr += 7; return; } - else if (gDisableStructs[index].unk6 != 0) + else if (gDisableStructs[bank].encoredMove != 0) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); return; @@ -2523,20 +2611,20 @@ void BattleAICmd_if_last_move_did_damage(void) gAIScriptPtr += 7; } -void BattleAICmd_if_encored(void) +static void BattleAICmd_if_curr_move_disabled_or_encored(void) { switch (gAIScriptPtr[1]) { - case 0: // _08109348 - if (gDisableStructs[gActiveBank].unk4 == AI_THINKING_STRUCT->moveConsidered) + case 0: + if (gDisableStructs[gActiveBank].disabledMove == AI_THINKING_STRUCT->moveConsidered) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); return; } gAIScriptPtr += 6; return; - case 1: // _08109370 - if (gDisableStructs[gActiveBank].unk6 == AI_THINKING_STRUCT->moveConsidered) + case 1: + if (gDisableStructs[gActiveBank].encoredMove == AI_THINKING_STRUCT->moveConsidered) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); return; @@ -2549,14 +2637,14 @@ void BattleAICmd_if_encored(void) } } -void BattleAICmd_flee(void) +static void BattleAICmd_flee(void) { - AI_THINKING_STRUCT->aiAction |= (AI_ACTION_UNK1 | AI_ACTION_UNK2 | AI_ACTION_UNK4); // what matters is UNK2 being enabled. + AI_THINKING_STRUCT->aiAction |= (AI_ACTION_DONE | AI_ACTION_FLEE | AI_ACTION_DO_NOT_ATTACK); // what matters is UNK2 being enabled. } -void BattleAICmd_if_random_100(void) +static void BattleAICmd_if_random_100(void) { - u8 safariFleeRate = gBattleStruct[0x7B] * 5; // safari flee rate, from 0-20 + u8 safariFleeRate = gBattleStruct->field_7B * 5; // safari flee rate, from 0-20 if ((u8)(Random() % 100) < safariFleeRate) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); @@ -2564,198 +2652,202 @@ void BattleAICmd_if_random_100(void) gAIScriptPtr += 5; } -void BattleAICmd_watch(void) +static void BattleAICmd_watch(void) { - AI_THINKING_STRUCT->aiAction |= (AI_ACTION_UNK1 | AI_ACTION_UNK3 | AI_ACTION_UNK4); // what matters is UNK3 being enabled. + AI_THINKING_STRUCT->aiAction |= (AI_ACTION_DONE | AI_ACTION_WATCH | AI_ACTION_DO_NOT_ATTACK); // what matters is UNK3 being enabled. } -void BattleAICmd_get_hold_effect(void) +static void BattleAICmd_get_hold_effect(void) { - u8 index; + u8 bank; u16 status; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; - if (gActiveBank != index) + if (gActiveBank != bank) { - AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(UNK_2016A00_STRUCT->unk44[index]); + AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(BATTLE_HISTORY->itemEffects[bank]); } else - AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(gBattleMons[index].item); + AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(gBattleMons[bank].item); gAIScriptPtr += 2; } -void tai62_unk(void) +static void BattleAICmd_if_holds_item(void) { - u8 index = sub_8131E70(gAIScriptPtr[1]); + u8 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); u16 item; u8 var1, var2; - - if((index & 1) == (gPlayerMonIndex & 1)) - item = gBattleMons[index].item; + + if ((bank & 1) == (sBank_AI & 1)) + item = gBattleMons[bank].item; else - item = UNK_2016A00_STRUCT->unk44[index]; + item = BATTLE_HISTORY->itemEffects[bank]; - // strange way of loading a 16-bit argument from the AI command. + // UB: doesn't properly read an unaligned u16 var2 = gAIScriptPtr[2]; var1 = gAIScriptPtr[3]; - - if((var1 | var2) == item) + + if ((var1 | var2) == item) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); else gAIScriptPtr += 8; } -void BattleAICmd_get_gender(void) +static void BattleAICmd_get_gender(void) { - u8 index; + u8 bank; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; - AI_THINKING_STRUCT->funcResult = pokemon_species_get_gender_info(gBattleMons[index].species, gBattleMons[index].personality); + AI_THINKING_STRUCT->funcResult = GetGenderFromSpeciesAndPersonality(gBattleMons[bank].species, gBattleMons[bank].personality); gAIScriptPtr += 2; } -void BattleAICmd_is_first_turn(void) +static void BattleAICmd_is_first_turn(void) { - u8 index; + u8 bank; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; - AI_THINKING_STRUCT->funcResult = gDisableStructs[index].unk16; + AI_THINKING_STRUCT->funcResult = gDisableStructs[bank].isFirstTurn; gAIScriptPtr += 2; } -void BattleAICmd_get_stockpile_count(void) +static void BattleAICmd_get_stockpile_count(void) { - u8 index; + u8 bank; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; - AI_THINKING_STRUCT->funcResult = gDisableStructs[index].unk9; + AI_THINKING_STRUCT->funcResult = gDisableStructs[bank].stockpileCounter; gAIScriptPtr += 2; } -void BattleAICmd_is_double_battle(void) +static void BattleAICmd_is_double_battle(void) { AI_THINKING_STRUCT->funcResult = gBattleTypeFlags & BATTLE_TYPE_DOUBLE; gAIScriptPtr += 1; } -void BattleAICmd_get_item(void) +static void BattleAICmd_get_used_held_item(void) { - u8 index; + u8 bank; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; - // this hack and a half matches. whatever. i dont care. someone else fix this mess later. PS: still cant fix this. - AI_THINKING_STRUCT->funcResult = gBattleStruct[0xB8 + (index * 2)]; + // This is likely a leftover from Ruby's code and its ugly ewram access + #ifdef NONMATCHING + AI_THINKING_STRUCT->funcResult = gBattleStruct->usedHeldItems[bank]; + #else + AI_THINKING_STRUCT->funcResult = *(u8*)((u8*)(gBattleStruct) + 0xB8 + (bank * 2)); + #endif // NONMATCHING gAIScriptPtr += 2; } -void BattleAICmd_get_move_type_from_result(void) +static void BattleAICmd_get_move_type_from_result(void) { AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].type; gAIScriptPtr += 1; } -void BattleAICmd_get_move_power_from_result(void) +static void BattleAICmd_get_move_power_from_result(void) { AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].power; gAIScriptPtr += 1; } -void BattleAICmd_get_move_effect_from_result(void) +static void BattleAICmd_get_move_effect_from_result(void) { AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].effect; gAIScriptPtr += 1; } -void BattleAICmd_get_protect_count(void) +static void BattleAICmd_get_protect_count(void) { - u8 index; + u8 bank; - if (gAIScriptPtr[1] == USER) - index = gPlayerMonIndex; + if (gAIScriptPtr[1] == AI_USER) + bank = sBank_AI; else - index = gBankTarget; + bank = gBankTarget; - AI_THINKING_STRUCT->funcResult = gDisableStructs[index].unk8; + AI_THINKING_STRUCT->funcResult = gDisableStructs[bank].protectUses; gAIScriptPtr += 2; } -void BattleAICmd_nullsub_52(void) +static void BattleAICmd_nullsub_52(void) { } -void BattleAICmd_nullsub_53(void) +static void BattleAICmd_nullsub_53(void) { } -void BattleAICmd_nullsub_54(void) +static void BattleAICmd_nullsub_54(void) { } -void BattleAICmd_nullsub_55(void) +static void BattleAICmd_nullsub_55(void) { } -void BattleAICmd_nullsub_56(void) +static void BattleAICmd_nullsub_56(void) { } -void BattleAICmd_nullsub_57(void) +static void BattleAICmd_nullsub_57(void) { } -void BattleAICmd_call(void) +static void BattleAICmd_call(void) { - b_mc_stack_push(gAIScriptPtr + 5); + AIStackPushVar(gAIScriptPtr + 5); gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); } -void BattleAICmd_jump(void) +static void BattleAICmd_jump(void) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); } -void BattleAICmd_end(void) +static void BattleAICmd_end(void) { - if (b_mc_stack_pop_cursor() == 0) - AI_THINKING_STRUCT->aiAction |= AI_ACTION_UNK1; + if (AIStackPop() == 0) + AI_THINKING_STRUCT->aiAction |= AI_ACTION_DONE; } -void BattleAICmd_if_level_cond(void) +static void BattleAICmd_if_level_cond(void) { switch (gAIScriptPtr[1]) { case 0: // greater than - if (gBattleMons[gPlayerMonIndex].level > gBattleMons[gBankTarget].level) + if (gBattleMons[sBank_AI].level > gBattleMons[gBankTarget].level) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); return; @@ -2763,7 +2855,7 @@ void BattleAICmd_if_level_cond(void) gAIScriptPtr += 6; return; case 1: // less than - if (gBattleMons[gPlayerMonIndex].level < gBattleMons[gBankTarget].level) + if (gBattleMons[sBank_AI].level < gBattleMons[gBankTarget].level) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); return; @@ -2771,7 +2863,7 @@ void BattleAICmd_if_level_cond(void) gAIScriptPtr += 6; return; case 2: // equal - if (gBattleMons[gPlayerMonIndex].level == gBattleMons[gBankTarget].level) + if (gBattleMons[sBank_AI].level == gBattleMons[gBankTarget].level) { gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); return; @@ -2781,56 +2873,56 @@ void BattleAICmd_if_level_cond(void) } } -void BattleAICmd_if_taunted(void) +static void BattleAICmd_if_target_taunted(void) { - if (gDisableStructs[gBankTarget].taunt != 0) + if (gDisableStructs[gBankTarget].tauntTimer1 != 0) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); else gAIScriptPtr += 5; } -void BattleAICmd_if_not_taunted(void) +static void BattleAICmd_if_target_not_taunted(void) { - if (gDisableStructs[gBankTarget].taunt == 0) + if (gDisableStructs[gBankTarget].tauntTimer1 == 0) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); else gAIScriptPtr += 5; } -void tai5E_unk(void) +static void BattleAICmd_if_target_is_ally(void) { - if((gPlayerMonIndex & 1) == (gBankTarget & 1)) + if((sBank_AI & 1) == (gBankTarget & 1)) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); else gAIScriptPtr += 5; } -void tai61_unk(void) +static void BattleAICmd_if_flash_fired(void) { - u8 index = sub_8131E70(gAIScriptPtr[1]); - - if(UNK_BATTLE_STRUCT->unk4->unkArray[index] & 1) + u8 index = BattleAI_GetWantedBank(gAIScriptPtr[1]); + + if(gBattleResources->flags->flags[index] & UNKNOWN_FLAG_FLASH_FIRE) gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); else gAIScriptPtr += 6; } -void b_mc_stack_push(u8 *var) +static void AIStackPushVar(u8 *var) { - UNK_2016C00_STRUCT->ptr[UNK_2016C00_STRUCT->unk20++] = var; + gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size++] = var; } -void b_mc_stack_push_cursor(void) +static void AIStackPushVar_cursor(void) { - UNK_2016C00_STRUCT->ptr[UNK_2016C00_STRUCT->unk20++] = gAIScriptPtr; + gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size++] = gAIScriptPtr; } -bool8 b_mc_stack_pop_cursor(void) +static bool8 AIStackPop(void) { - if (UNK_2016C00_STRUCT->unk20 != 0) + if (gBattleResources->AI_ScriptsStack->size != 0) { - --UNK_2016C00_STRUCT->unk20; - gAIScriptPtr = UNK_2016C00_STRUCT->ptr[UNK_2016C00_STRUCT->unk20]; + --gBattleResources->AI_ScriptsStack->size; + gAIScriptPtr = gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size]; return TRUE; } else diff --git a/src/calculate_base_damage.c b/src/calculate_base_damage.c new file mode 100644 index 000000000..105b334f2 --- /dev/null +++ b/src/calculate_base_damage.c @@ -0,0 +1,284 @@ +#include "global.h" +#include "abilities.h" +#include "battle.h" +#include "hold_effects.h" +#include "event_data.h" +#include "item.h" +#include "items.h" +#include "pokemon.h" +#include "species.h" +#include "moves.h" +#include "battle_move_effects.h" + +extern u32 gBattleTypeFlags; +extern struct BattlePokemon gBattleMons[4]; +extern u16 gCurrentMove; +extern u8 gCritMultiplier; +extern u16 gBattleWeather; +extern struct BattleEnigmaBerry gEnigmaBerries[]; +extern u16 gBattleMovePower; +extern u16 gTrainerBattleOpponent_A; + +u8 CountAliveMonsInBattle(u8); +bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 bank); + +extern const struct BattleMove gBattleMoves[]; +extern const u8 gHoldEffectToType[][2]; +extern const u8 gStatStageRatios[][2]; + +#define APPLY_STAT_MOD(var, mon, stat, statIndex) \ +{ \ + (var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \ + (var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \ +} + +s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef) +{ + u32 i; + s32 damage = 0; + s32 damageHelper; + u8 type; + u16 attack, defense; + u16 spAttack, spDefense; + u8 defenderHoldEffect; + u8 defenderHoldEffectParam; + u8 attackerHoldEffect; + u8 attackerHoldEffectParam; + + if (!powerOverride) + gBattleMovePower = gBattleMoves[move].power; + else + gBattleMovePower = powerOverride; + + if (!typeOverride) + type = gBattleMoves[move].type; + else + type = typeOverride & 0x3F; + + attack = attacker->attack; + defense = defender->defense; + spAttack = attacker->spAttack; + spDefense = defender->spDefense; + + if (attacker->item == ITEM_ENIGMA_BERRY) + { + attackerHoldEffect = gEnigmaBerries[bankAtk].holdEffect; + attackerHoldEffectParam = gEnigmaBerries[bankAtk].holdEffectParam; + } + else + { + attackerHoldEffect = ItemId_GetHoldEffect(attacker->item); + attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item); + } + + if (defender->item == ITEM_ENIGMA_BERRY) + { + defenderHoldEffect = gEnigmaBerries[bankDef].holdEffect; + defenderHoldEffectParam = gEnigmaBerries[bankDef].holdEffectParam; + } + else + { + defenderHoldEffect = ItemId_GetHoldEffect(defender->item); + defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item); + } + + if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER) + attack *= 2; + + if (ShouldGetStatBadgeBoost(BADGE01_GET, bankAtk)) + attack = (110 * attack) / 100; + if (ShouldGetStatBadgeBoost(BADGE05_GET, bankDef)) + defense = (110 * defense) / 100; + if (ShouldGetStatBadgeBoost(BADGE07_GET, bankAtk)) + spAttack = (110 * spAttack) / 100; + if (ShouldGetStatBadgeBoost(BADGE07_GET, bankDef)) + spDefense = (110 * spDefense) / 100; + + for (i = 0; i < 17; i++) + { + if (attackerHoldEffect == gHoldEffectToType[i][0] + && type == gHoldEffectToType[i][1]) + { + if (type <= 8) + attack = (attack * (attackerHoldEffectParam + 100)) / 100; + else + spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100; + break; + } + } + + if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND) + attack = (150 * attack) / 100; + if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS)) + spAttack = (150 * spAttack) / 100; + if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS)) + spDefense = (150 * spDefense) / 100; + if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL) + spAttack *= 2; + if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL) + spDefense *= 2; + if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU) + spAttack *= 2; + if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO) + defense *= 2; + if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK)) + attack *= 2; + if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE)) + spAttack /= 2; + if (attacker->ability == ABILITY_HUSTLE) + attack = (150 * attack) / 100; + if (attacker->ability == ABILITY_PLUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MINUS, 0, 0)) + spAttack = (150 * spAttack) / 100; + if (attacker->ability == ABILITY_MINUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_PLUS, 0, 0)) + spAttack = (150 * spAttack) / 100; + if (attacker->ability == ABILITY_GUTS && attacker->status1) + attack = (150 * attack) / 100; + if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1) + defense = (150 * defense) / 100; + if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0)) + gBattleMovePower /= 2; + if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0)) + gBattleMovePower /= 2; + if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) + defense /= 2; + + if (type < TYPE_MYSTERY) // is physical + { + if (gCritMultiplier == 2) + { + if (attacker->statStages[STAT_STAGE_ATK] > 6) + APPLY_STAT_MOD(damage, attacker, attack, STAT_STAGE_ATK) + else + damage = attack; + } + else + APPLY_STAT_MOD(damage, attacker, attack, STAT_STAGE_ATK) + + damage = damage * gBattleMovePower; + damage *= (2 * attacker->level / 5 + 2); + + if (gCritMultiplier == 2) + { + if (defender->statStages[STAT_STAGE_DEF] < 6) + APPLY_STAT_MOD(damageHelper, defender, defense, STAT_STAGE_DEF) + else + damageHelper = defense; + } + else + APPLY_STAT_MOD(damageHelper, defender, defense, STAT_STAGE_DEF) + + damage = damage / damageHelper; + damage /= 50; + + if ((attacker->status1 & STATUS_BURN) && attacker->ability != ABILITY_GUTS) + damage /= 2; + + if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2) + damage = 2 * (damage / 3); + else + damage /= 2; + } + + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2) + damage /= 2; + + // moves always do at least 1 damage. + if (damage == 0) + damage = 1; + } + + if (type == TYPE_MYSTERY) + damage = 0; // is ??? type. does 0 damage. + + if (type > TYPE_MYSTERY) // is special? + { + if (gCritMultiplier == 2) + { + if (attacker->statStages[STAT_STAGE_SPATK] > 6) + APPLY_STAT_MOD(damage, attacker, spAttack, STAT_STAGE_SPATK) + else + damage = spAttack; + } + else + APPLY_STAT_MOD(damage, attacker, spAttack, STAT_STAGE_SPATK) + + damage = damage * gBattleMovePower; + damage *= (2 * attacker->level / 5 + 2); + + if (gCritMultiplier == 2) + { + if (defender->statStages[STAT_STAGE_SPDEF] < 6) + APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_STAGE_SPDEF) + else + damageHelper = spDefense; + } + else + APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_STAGE_SPDEF) + + damage = (damage / damageHelper); + damage /= 50; + + if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2) + damage = 2 * (damage / 3); + else + damage /= 2; + } + + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2) + damage /= 2; + + // are effects of weather negated with cloud nine or air lock + if (!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0) + && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0)) + { + if (gBattleWeather & WEATHER_RAIN_TEMPORARY) + { + switch (type) + { + case TYPE_FIRE: + damage /= 2; + break; + case TYPE_WATER: + damage = (15 * damage) / 10; + break; + } + } + + // any weather except sun weakens solar beam + if ((gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SANDSTORM_ANY | WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM) + damage /= 2; + + // sunny + if (gBattleWeather & WEATHER_SUN_ANY) + { + switch (type) + { + case TYPE_FIRE: + damage = (15 * damage) / 10; + break; + case TYPE_WATER: + damage /= 2; + break; + } + } + } + + // flash fire triggered + if ((gBattleResources->flags->flags[bankAtk] & UNKNOWN_FLAG_FLASH_FIRE) && type == TYPE_FIRE) + damage = (15 * damage) / 10; + } + + return damage + 2; +} diff --git a/src/load_save.c b/src/load_save.c new file mode 100644 index 000000000..588387186 --- /dev/null +++ b/src/load_save.c @@ -0,0 +1,114 @@ +#include "global.h" +#include "gba/flash_internal.h" +#include "load_save.h" +#include "main.h" +#include "pokemon.h" +#include "rng.h" +#include "malloc.h" + +extern u8 gPlayerPartyCount; +extern struct PokemonStorage* gPokemonStoragePtr; +extern void* gUnknown_0203CF5C; +extern u8 gHeap[0x1C000]; + +extern bool16 IdentifyFlash(void); +extern void SetBagItemsPointers(void); +extern void SetDecorationInventoriesPointers(void); +extern void InitHeap(void *heapStart, u32 heapSize); + +void ApplyNewEncyprtionKeyToAllEncryptedData(u32 encryptionKey); + +#define SAVEBLOCK_MOVE_RANGE 128 + +EWRAM_DATA struct SaveBlock2 gSaveblock2 = {0}; +EWRAM_DATA u8 gSaveblock2_DMA[SAVEBLOCK_MOVE_RANGE] = {0}; + +EWRAM_DATA struct SaveBlock1 gSaveblock1 = {0}; +EWRAM_DATA u8 gSaveblock1_DMA[SAVEBLOCK_MOVE_RANGE] = {0}; + +EWRAM_DATA struct PokemonStorage gPokemonStorage = {0}; +EWRAM_DATA u8 gSaveblock3_DMA[SAVEBLOCK_MOVE_RANGE] = {0}; + +void CheckForFlashMemory(void) +{ + if (!IdentifyFlash()) + { + gFlashMemoryPresent = TRUE; + InitFlashTimer(); + } + else + gFlashMemoryPresent = FALSE; +} + +void ClearSav2(void) +{ + CpuFill16(0, &gSaveblock2, sizeof(struct SaveBlock2) + sizeof(gSaveblock2_DMA)); +} + +void ClearSav1(void) +{ + CpuFill16(0, &gSaveblock1, sizeof(struct SaveBlock1) + sizeof(gSaveblock1_DMA)); +} + +void SetSaveBlocksPointers(u16 offset) +{ + struct SaveBlock1** sav1_LocalVar = &gSaveBlock1Ptr; + + offset = (offset + Random()) & (SAVEBLOCK_MOVE_RANGE - 4); + + gSaveBlock2Ptr = (void*)(&gSaveblock2) + offset; + *sav1_LocalVar = (void*)(&gSaveblock1) + offset; + gPokemonStoragePtr = (void*)(&gPokemonStorage) + offset; + + SetBagItemsPointers(); + SetDecorationInventoriesPointers(); +} + +struct SaveBlocksInOne +{ + struct SaveBlock2 sav2; + struct SaveBlock1 sav1; + struct PokemonStorage sav3; +}; +/* +void MoveSaveBlocks_ResetHeap(void) +{ + void *vblankCB, *hblankCB; + u32 encryptionKey; + struct SaveBlocksInOne* copiedSavs; + + // save interrupt functions and turn them off + vblankCB = gMain.vblankCallback; + hblankCB = gMain.hblankCallback; + gMain.vblankCallback = NULL; + gMain.hblankCallback = NULL; + gUnknown_0203CF5C = NULL; + + copiedSavs = (void*)(gHeap); + + // copy saveblocks' content + copiedSavs->sav2 = *gSaveBlock2Ptr; + copiedSavs->sav1 = *gSaveBlock1Ptr; + copiedSavs->sav3 = *gPokemonStoragePtr; + + // change saveblocks' pointers + // argument is a sum of the individual trainerId bytes + SetSaveBlocksPointers(copiedSavs->sav2.playerTrainerId[0] + copiedSavs->sav2.playerTrainerId[1] + copiedSavs->sav2.playerTrainerId[2] + copiedSavs->sav2.playerTrainerId[3]); + + // restore saveblock data since the pointers changed + *gSaveBlock2Ptr = copiedSavs->sav2; + *gSaveBlock1Ptr = copiedSavs->sav1; + *gPokemonStoragePtr = copiedSavs->sav3; + + // heap was destroyed in the copying process, so reset it + InitHeap(gHeap, sizeof(gHeap)); + + // restore interrupt functions + gMain.hblankCallback = hblankCB; + gMain.vblankCallback = vblankCB; + + // create a new encryption key + encryptionKey = (Random() << 0x10) + (Random()); + ApplyNewEncyprtionKeyToAllEncryptedData(encryptionKey); + gSaveBlock2Ptr->encryptionKey = encryptionKey; +}*/ diff --git a/src/main.c b/src/main.c index 7c8075a6f..15f1ec3eb 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include "rng.h" #include "dma3.h" #include "gba/flash_internal.h" +#include "battle.h" extern u16 GetGpuReg(u8); extern void SetGpuReg(u8, u16); @@ -34,9 +35,9 @@ extern struct SoundInfo gSoundInfo; extern u32 gFlashMemoryPresent; extern u32 IntrMain[]; extern u8 gHeap[]; -extern struct SaveBlock2 gUnknown_02024A54; -extern char *gUnknown_03005D94; -extern char gUnknown_02029808[]; +extern struct SaveBlock2 gSaveblock2; +extern char *gPokemonStoragePtr; +extern char gPokemonStorage[]; extern u32 gBattleTypeFlags; extern u8 gUnknown_03002748; extern u32 *gUnknown_0203CF5C; @@ -185,8 +186,8 @@ static void InitMainCallbacks(void) gMain.vblankCounter2 = 0; gMain.callback1 = NULL; SetMainCallback2(c2_copyright_1); - gSaveBlock2Ptr = &gUnknown_02024A54; - gUnknown_03005D94 = gUnknown_02029808; + gSaveBlock2Ptr = &gSaveblock2; + gPokemonStoragePtr = gPokemonStorage; } static void CallCallbacks(void) @@ -359,7 +360,7 @@ static void VBlankIntr(void) m4aSoundMain(); sub_8033648(); - if (!gMain.inBattle || (gBattleTypeFlags & 0x013F0102) == 0) + if (!gMain.inBattle || !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_RECORDED))) Random(); sub_800E174(); @@ -368,7 +369,7 @@ static void VBlankIntr(void) gMain.intrCheck |= INTR_FLAG_VBLANK; } -void StartFlashMemoryTimer(void) +void InitFlashTimer(void) { SetFlashTimerIntr(2, gIntrTable + 0x7); } diff --git a/src/malloc.c b/src/malloc.c index 948303c6f..3901c5a35 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -1,7 +1,5 @@ #include "global.h" -EWRAM_DATA u8 gHeap[0x1C000] = {0}; - static void *sHeapStart; static u32 sHeapSize; diff --git a/src/palette.c b/src/palette.c index eb055a294..aa9a84e4c 100644 --- a/src/palette.c +++ b/src/palette.c @@ -54,7 +54,7 @@ EWRAM_DATA struct PaletteStruct sPaletteStructs[0x10] = {0}; EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0}; EWRAM_DATA u32 gFiller_2037FE0 = 0; EWRAM_DATA u32 sPlttBufferTransferPending = 0; -EWRAM_DATA u8 sPaletteDecompressionBuffer[0x400] = {0}; +EWRAM_DATA u8 gPaletteDecompressionBuffer[0x400] = {0}; extern struct PaletteStructTemplate gDummyPaletteStructTemplate; extern void *gUnknown_0852487C; @@ -102,9 +102,9 @@ void sub_80A1884(u16 a1) void LoadCompressedPalette(const void *src, u16 offset, u16 size) { - LZDecompressWram(src, sPaletteDecompressionBuffer); - CpuCopy16(sPaletteDecompressionBuffer, gPlttBufferUnfaded + offset, size); - CpuCopy16(sPaletteDecompressionBuffer, gPlttBufferFaded + offset, size); + LZDecompressWram(src, gPaletteDecompressionBuffer); + CpuCopy16(gPaletteDecompressionBuffer, gPlttBufferUnfaded + offset, size); + CpuCopy16(gPaletteDecompressionBuffer, gPlttBufferFaded + offset, size); } void LoadPalette(const void *src, u16 offset, u16 size) diff --git a/src/save.c b/src/save.c index ccb653f66..2b3da38b1 100644 --- a/src/save.c +++ b/src/save.c @@ -5,7 +5,7 @@ extern struct SaveSectionOffsets gSaveSectionOffsets[0xE]; extern struct SaveSectionLocation gRamSaveSectionLocations[0xE]; -extern void *gUnknown_03005D94; +extern void *gPokemonStoragePtr; extern u8 gDecompressionBuffer[]; extern u32 gFlashMemoryPresent; extern u16 gUnknown_03006294; @@ -593,7 +593,7 @@ void UpdateSaveAddresses(void) for(i = 5; i < 14; i++) { - gRamSaveSectionLocations[i].data = gUnknown_03005D94 + gSaveSectionOffsets[i].toAdd; + gRamSaveSectionLocations[i].data = gPokemonStoragePtr + gSaveSectionOffsets[i].toAdd; gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size; } } @@ -630,7 +630,7 @@ _081531AC:\n\ bge _081531AC\n\ movs r4, 0x5\n\ ldr r1, =gRamSaveSectionLocations\n\ - ldr r5, =gUnknown_03005D94\n\ + ldr r5, =gPokemonStoragePtr\n\ ldr r0, =gSaveSectionOffsets\n\ adds r3, r1, 0\n\ adds r3, 0x28\n\ diff --git a/src/start_menu.c b/src/start_menu.c new file mode 100644 index 000000000..ffcab5220 --- /dev/null +++ b/src/start_menu.c @@ -0,0 +1,231 @@ +#include "global.h" +#include "start_menu.h" +#include "menu.h" +#include "safari_zone.h" +#include "event_data.h" +#include "window.h" +#include "string_util.h" +#include "text.h" + +// Menu actions +enum +{ + MENU_ACTION_POKEDEX, + MENU_ACTION_POKEMON, + MENU_ACTION_BAG, + MENU_ACTION_POKENAV, + MENU_ACTION_PLAYER, + MENU_ACTION_SAVE, + MENU_ACTION_OPTION, + MENU_ACTION_EXIT, + MENU_ACTION_RETIRE_SAFARI, + MENU_ACTION_PLAYER_LINK, + MENU_ACTION_REST_FRONTIER, + MENU_ACTION_RETIRE_FRONTIER, + MENU_ACTION_PYRAMID_BAG +}; + +static void BuildStartMenuActions_LinkMode(void); +static void BuildStartMenuActions_UnionRoom(void); +static void BuildStartMenuActions_SafariZone(void); +static void BuildStartMenuActions_BattlePike(void); +static void BuildStartMenuActions_BattlePyramid(void); +static void BuildStartMenuActions_MultiBattleRoom(void); +static void BuildStartMenuActions_Normal(void); +u8 StartMenu_PlayerName(void); + +extern bool32 is_c1_link_related_active(void); +extern bool32 InUnionRoom(void); +extern bool8 InBattlePike(void); +extern bool8 InBattlePyramid(void); +extern bool8 InMultiBattleRoom(void); +extern void sub_81973FC(u8 windowId, u8 a1); +extern void sub_8198070(u8 windowId, u8 a1); + +EWRAM_DATA u8 sSafariBallsWindowId = 0; +EWRAM_DATA u8 sBattlePyramidFloorWindowId = 0; +EWRAM_DATA u8 sStartMenuCursorPos = 0; +EWRAM_DATA u8 sNumStartMenuActions = 0; +EWRAM_DATA u8 sCurrentStartMenuActions[9] = {0}; + +void BuildStartMenuActions(void) +{ + sNumStartMenuActions = 0; + if (is_c1_link_related_active() == TRUE) + BuildStartMenuActions_LinkMode(); + else if (InUnionRoom() == TRUE) + BuildStartMenuActions_UnionRoom(); + else if (GetSafariZoneFlag() == TRUE) + BuildStartMenuActions_SafariZone(); + else if (InBattlePike()) + BuildStartMenuActions_BattlePike(); + else if (InBattlePyramid()) + BuildStartMenuActions_BattlePyramid(); + else if (InMultiBattleRoom()) + BuildStartMenuActions_MultiBattleRoom(); + else + BuildStartMenuActions_Normal(); +} + +void AddStartMenuAction(u8 action) +{ + AppendToList(sCurrentStartMenuActions, &sNumStartMenuActions, action); +} + +static void BuildStartMenuActions_Normal(void) +{ + if (FlagGet(SYS_POKEDEX_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKEDEX); + if (FlagGet(SYS_POKEMON_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(SYS_POKENAV_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKENAV); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_SAVE); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_SafariZone(void) +{ + AddStartMenuAction(MENU_ACTION_RETIRE_SAFARI); + AddStartMenuAction(MENU_ACTION_POKEDEX); + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_LinkMode(void) +{ + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(SYS_POKENAV_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKENAV); + AddStartMenuAction(MENU_ACTION_PLAYER_LINK); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_UnionRoom(void) +{ + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(SYS_POKENAV_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKENAV); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_BattlePike(void) +{ + AddStartMenuAction(MENU_ACTION_POKEDEX); + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_BattlePyramid(void) +{ + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_PYRAMID_BAG); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_REST_FRONTIER); + AddStartMenuAction(MENU_ACTION_RETIRE_FRONTIER); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_MultiBattleRoom(void) +{ + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +extern const struct WindowTemplate gSafariBallsWindowTemplate; +extern const struct WindowTemplate gPyramidFloorWindowTemplate_1; +extern const struct WindowTemplate gPyramidFloorWindowTemplate_2; +extern const u8 gOtherText_SafariStock[]; + +void DisplaySafariBallsWindow(void) +{ + sSafariBallsWindowId = AddWindow(&gSafariBallsWindowTemplate); + PutWindowTilemap(sSafariBallsWindowId); + sub_81973FC(sSafariBallsWindowId, 0); + ConvertIntToDecimalStringN(gStringVar1, gNumSafariBalls, STR_CONV_MODE_RIGHT_ALIGN, 2); + StringExpandPlaceholders(gStringVar4, gOtherText_SafariStock); + PrintTextOnWindow(sSafariBallsWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL); + CopyWindowToVram(sSafariBallsWindowId, 2); +} + +extern const u8* const gUnknown_08510510[]; +extern const u8 gOtherText_BattlePyramid_X[]; + +void DisplayPyramidFloorWindow(void) +{ + // TODO: fix location + if (*(u16*)(&gSaveBlock2Ptr->field_CAA[8]) == 7) + sBattlePyramidFloorWindowId = AddWindow(&gPyramidFloorWindowTemplate_1); + else + sBattlePyramidFloorWindowId = AddWindow(&gPyramidFloorWindowTemplate_2); + PutWindowTilemap(sBattlePyramidFloorWindowId); + sub_81973FC(sBattlePyramidFloorWindowId, 0); + StringCopy(gStringVar1, gUnknown_08510510[*(u16*)(&gSaveBlock2Ptr->field_CAA[8])]); + StringExpandPlaceholders(gStringVar4, gOtherText_BattlePyramid_X); + PrintTextOnWindow(sBattlePyramidFloorWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL); + CopyWindowToVram(sBattlePyramidFloorWindowId, 2); +} + +void RemoveExtraStartMenuWindows(void) +{ + if (GetSafariZoneFlag()) + { + sub_8198070(sSafariBallsWindowId, 0); + CopyWindowToVram(sSafariBallsWindowId, 2); + RemoveWindow(sSafariBallsWindowId); + } + if (InBattlePyramid()) + { + sub_8198070(sBattlePyramidFloorWindowId, 0); + RemoveWindow(sBattlePyramidFloorWindowId); + } +} + +extern const struct MenuAction sStartMenuItems[]; + +/* +// Prints n menu items starting at *index +static bool32 PrintStartMenuItemsMultistep(s16 *index, u32 n) +{ + s8 _index = *index; + + do + { + if (sStartMenuItems[sCurrentStartMenuActions[_index]].func == StartMenu_PlayerName) + { + + } + else + { + + } + + } while (++_index > sNumStartMenuActions); + + if (--n == 0) + { + *index = _index; + return FALSE; + } + else + { + *index = _index; + return TRUE; + } +}*/ diff --git a/src/text.c b/src/text.c index 6754e1a42..cad8326e3 100644 --- a/src/text.c +++ b/src/text.c @@ -149,7 +149,7 @@ void DeactivateAllTextPrinters (void) gTextPrinters[printer].sub_union.sub.active = 0; } -u16 Print(u8 windowId, u8 fontId, u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextSubPrinter *, u16)) +u16 PrintTextOnWindow(u8 windowId, u8 fontId, u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextSubPrinter *, u16)) { struct TextSubPrinter subPrinter; diff --git a/src/window.c b/src/window.c index f3d2e833e..574b13aa0 100644 --- a/src/window.c +++ b/src/window.c @@ -118,7 +118,7 @@ bool16 InitWindows(struct WindowTemplate *templates) return TRUE; } -u16 AddWindow(struct WindowTemplate *template) +u16 AddWindow(const struct WindowTemplate *template) { u16 win; u8 bgLayer; |