diff --git a/asm/macros/battle_frontier/battle_dome.inc b/asm/macros/battle_frontier/battle_dome.inc index 9adbcc54e7ed..13f77638102d 100644 --- a/asm/macros/battle_frontier/battle_dome.inc +++ b/asm/macros/battle_frontier/battle_dome.inc @@ -57,7 +57,7 @@ special CallBattleDomeFunction .endm - @ Sets gTrainerBattleOpponent_A to the trainer ID of the next opponent + @ Sets TRAINER_BATTLE_PARAM.battleOpponentA to the trainer ID of the next opponent .macro dome_setopponent setvar VAR_0x8004, BATTLE_DOME_FUNC_SET_OPPONENT_ID special CallBattleDomeFunction diff --git a/asm/macros/battle_frontier/battle_tower.inc b/asm/macros/battle_frontier/battle_tower.inc index b3c86955dd78..56c0ff5fc135 100644 --- a/asm/macros/battle_frontier/battle_tower.inc +++ b/asm/macros/battle_frontier/battle_tower.inc @@ -115,14 +115,13 @@ .macro multi_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req special SavePlayerParty - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, \trainer1Id, 0, NULL, \trainer1LoseText @ set first trainer mons - trainerbattle TRAINER_BATTLE_SET_TRAINER_B, \trainer2Id, 0, NULL, \trainer2LoseText @ set second trainer mons + setmultitrainerbattle \trainer1Id, \trainer1LoseText, \trainer2Id, \trainer2LoseText multi_do MULTI_BATTLE_2_VS_2, \partnerId .endm .macro multi_2_vs_1 trainer1Id:req, trainer1LoseText:req, partnerId:req special SavePlayerParty - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, \trainer1Id, 0, NULL, \trainer1LoseText @ set first trainer mons + setmultitrainerbattle \trainer1Id, \trainer1LoseText, TRAINER_NONE, NULL multi_do MULTI_BATTLE_2_VS_1, \partnerId .endm @@ -145,14 +144,13 @@ .macro multi_fixed_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req special SavePlayerParty - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, \trainer1Id, 0, NULL, \trainer1LoseText @ set first trainer mons - trainerbattle TRAINER_BATTLE_SET_TRAINER_B, \trainer2Id, 0, NULL, \trainer2LoseText @ set second trainer mons + setmultitrainerbattle \trainer1Id, \trainer1LoseText, \trainer2Id, \trainer2LoseText multi_do_fixed MULTI_BATTLE_2_VS_2, \partnerId .endm .macro multi_fixed_2_vs_1 trainer1Id:req, trainer1LoseText:req, partnerId:req special SavePlayerParty - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, \trainer1Id, 0, NULL, \trainer1LoseText @ set first trainer mons + setmultitrainerbattle \trainer1Id, \trainer1LoseText, TRAINER_NONE, NULL multi_do_fixed MULTI_BATTLE_2_VS_1, \partnerId .endm diff --git a/asm/macros/battle_frontier/frontier_util.inc b/asm/macros/battle_frontier/frontier_util.inc index e40eccb5e7e1..10248b0476d9 100644 --- a/asm/macros/battle_frontier/frontier_util.inc +++ b/asm/macros/battle_frontier/frontier_util.inc @@ -133,7 +133,7 @@ special CallFrontierUtilFunc .endm - @ Buffer the name of gTrainerBattleOpponent_A in STR_VAR_1 (0) or STR_VAR_2 (1) + @ Buffer the name of TRAINER_BATTLE_PARAM.battleOpponentA in STR_VAR_1 (0) or STR_VAR_2 (1) .macro frontier_gettrainername stringVar:req setvar VAR_0x8004, FRONTIER_UTIL_FUNC_BUFFER_TRAINER_NAME .if \stringVar == STR_VAR_1 diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 2bb2027cb1a4..6776348f9522 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -680,72 +680,41 @@ .byte \direction .endm + NULL = 0 + OBJ_ID_NONE = 0 + @ Configures the arguments for a trainer battle, then jumps to the appropriate script in scripts/trainer_battle.inc - .macro trainerbattle type:req, trainer:req, local_id:req, pointer1:req, pointer2, pointer3, pointer4 + .macro trainerbattle localIdA:req, trainer_a:req, intro_text_a:req, lose_text_a:req, event_script_a:req, localIdB:req, trainer_b:req, intro_text_b:req, lose_text_b:req, event_script_b:req, victory_text:req, cannot_battle:req, isDouble:req, playMusicA:req, playMusicB:req, isRematch:req .byte 0x5c - .byte \type - .2byte \trainer - .2byte \local_id - .if \type == TRAINER_BATTLE_SINGLE - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .elseif \type == TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .4byte \pointer3 @ event script - .elseif \type == TRAINER_BATTLE_CONTINUE_SCRIPT - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .4byte \pointer3 @ event script - .elseif \type == TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT - .4byte \pointer1 @ text - .elseif \type == TRAINER_BATTLE_DOUBLE - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .4byte \pointer3 @ text - .elseif \type == TRAINER_BATTLE_REMATCH - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .elseif \type == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .4byte \pointer3 @ text - .4byte \pointer4 @ event script - .elseif \type == TRAINER_BATTLE_REMATCH_DOUBLE - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .4byte \pointer3 @ text - .elseif \type == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .4byte \pointer3 @ text - .4byte \pointer4 @ event script - .elseif \type == TRAINER_BATTLE_PYRAMID - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .elseif \type == TRAINER_BATTLE_SET_TRAINER_A - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .elseif \type == TRAINER_BATTLE_SET_TRAINER_B - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .elseif \type == TRAINER_BATTLE_HILL - .4byte \pointer1 @ text - .4byte \pointer2 @ text - .endif + .set trainerbattle_flags, 0 + .ifgt \isDouble; .set trainerbattle_flags, trainerbattle_flags | (1 << 0); .endif + .ifgt \isRematch; .set trainerbattle_flags, trainerbattle_flags | (1 << 1); .endif + .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif + .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 3); .endif + .byte trainerbattle_flags + .byte \localIdA @ objEventLocalIdA + .2byte \trainer_a @ battleOpponentA + .4byte \intro_text_a @ introTextA + .4byte \lose_text_a @ defeatTextA + .4byte \event_script_a @ retAddrA + .byte \localIdB @ objEventLocalIdB + .2byte \trainer_b @ battleOpponentB + .4byte \intro_text_b @ introTextB + .4byte \lose_text_b @ defeatTextB + .4byte \event_script_b @ retAddrB + .4byte \victory_text @ victoryText + .4byte \cannot_battle @ cannotBattle .endm - NO_MUSIC = FALSE - @ Starts a single trainer battle. Takes a trainer, intro text, loss text, and an optional event script. @ When used with an event script, you can also pass in an optional flag to disable music .macro trainerbattle_single trainer:req, intro_text:req, lose_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_SINGLE, \trainer, 0, \intro_text, \lose_text + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE .endif .endm @@ -753,38 +722,27 @@ @ and an optional event script. When used with an event script you can pass in an optional flag to disable music .macro trainerbattle_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE .endif .endm @ Starts a rematch battle. Takes a trainer, intro text and loss text .macro trainerbattle_rematch trainer:req, intro_text:req, lose_text:req - trainerbattle TRAINER_BATTLE_REMATCH, \trainer, 0, \intro_text, \lose_text + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE .endm @ Starts a rematch double battle. Takes a trainer, intro text, loss text, and text for when you have too few pokemon .macro trainerbattle_rematch_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req - trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, \trainer, 0, \lose_text - .endm - - @ Starts a double battle with the player against two trainers - @ Takes two trainers and defeat text for each - .macro trainerbattle_two_trainers trainer_a:req, lose_text_a:req, trainer_b:req, lose_text_b:req - .byte 0x5c - .byte TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO - .2byte \trainer_a - .4byte \lose_text_a - .2byte \trainer_b - .4byte \lose_text_b + trainerbattle OBJ_ID_NONE, \trainer, NULL, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .endm @ Starts a trainer battle using the battle information stored in RAM (usually by the scripts in trainer_battle.inc, which @@ -1892,6 +1850,19 @@ _dynmultichoice \left, \top, \ignoreBPress, \maxBeforeScroll, \shouldSort, \initialSelected, \callbacks, NULL .endm + .macro setmultitrainerbattle trainer_a:req, lose_text_a:req, trainer_b:req, lose_text_b:req + .byte 0xe5 + .2byte \trainer_a + .4byte \lose_text_a + .2byte \trainer_b + .4byte \lose_text_b + .endm + + .macro facilitytrainerbattle type:req + .byte 0xe6 + .byte \type + .endm + @ Supplementary .macro goto_if_unset flag:req, dest:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f40fa85e1aa6..6b70de813a9e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5597,7 +5597,7 @@ BattleScript_LocalBattleLost:: jumpifbattletype BATTLE_TYPE_FRONTIER, BattleScript_LocalBattleLostPrintTrainersWinText jumpifbattletype BATTLE_TYPE_TRAINER_HILL, BattleScript_LocalBattleLostPrintTrainersWinText jumpifbattletype BATTLE_TYPE_EREADER_TRAINER, BattleScript_LocalBattleLostEnd - jumpifhalfword CMP_EQUAL, gTrainerBattleOpponent_A, TRAINER_SECRET_BASE, BattleScript_LocalBattleLostEnd + jumpifhalfword CMP_EQUAL, gTrainerBattleParameter + 2, TRAINER_SECRET_BASE, BattleScript_LocalBattleLostEnd @ gTrainerBattleParameter + 2 is gTrainerBattleParameter.params.battleOpponentA BattleScript_LocalBattleLostPrintWhiteOut:: .if B_WHITEOUT_MONEY >= GEN_4 jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_LocalBattleLostEnd diff --git a/data/event_scripts.s b/data/event_scripts.s index 71bc884308b6..6493f6f181cf 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -88,7 +88,7 @@ gSpecialVars:: .4byte gSpecialVar_MonBoxId .4byte gSpecialVar_MonBoxPos .4byte gSpecialVar_Unused_0x8014 - .4byte gTrainerBattleOpponent_A + .4byte gTrainerBattleParameter + 2 // gTrainerBattleParameter.params.battleOpponentA .include "data/specials.inc" diff --git a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index ba9d9967062f..b921fafacf13 100644 --- a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc +++ b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc @@ -105,7 +105,7 @@ BattlePyramid_WarpToTop:: @ TRAINER_PHILLIP is used as a placeholder BattlePyramid_TrainerBattle:: - trainerbattle TRAINER_BATTLE_PYRAMID, TRAINER_PHILLIP, 0, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText + facilitytrainerbattle TRAINER_BATTLE_PYRAMID pyramid_showhint waitmessage waitbuttonpress diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index b7db13f54a0e..b65ebf9e485c 100644 --- a/data/maps/LavaridgeTown_Gym_1F/scripts.inc +++ b/data/maps/LavaridgeTown_Gym_1F/scripts.inc @@ -104,7 +104,7 @@ LavaridgeTown_Gym_1F_EventScript_FlanneryRematch:: end LavaridgeTown_Gym_1F_EventScript_Cole:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_COLE, LOCALID_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_ColePostBattle, MSGBOX_AUTOCLOSE end @@ -116,37 +116,37 @@ LavaridgeTown_Gym_EventScript_CheckTrainerScript:: end LavaridgeTown_Gym_1F_EventScript_Axle:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_AXLE, LOCALID_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_AxlePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Keegan:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_KEEGAN, LOCALID_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_KeeganPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Danielle:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_DANIELLE, LOCALID_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_DaniellePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Gerald:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_GERALD, LOCALID_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_GeraldPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jace:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_JACE, LOCALID_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JacePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jeff:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_JEFF, LOCALID_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JeffPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Eli:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, TRAINER_ELI, LOCALID_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript + trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, OBJ_ID_NONE, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_EliPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/script_cmd_table.inc b/data/script_cmd_table.inc index 711b118cc6ef..3542fe44252d 100644 --- a/data/script_cmd_table.inc +++ b/data/script_cmd_table.inc @@ -229,6 +229,8 @@ gScriptCmdTable:: .4byte ScrCmd_bufferitemnameplural @ 0xe2 .4byte ScrCmd_dynmultichoice @ 0xe3 .4byte ScrCmd_dynmultipush @ 0xe4 + .4byte ScrCmd_setmultitrainerbattle @ 0xe5 + .4byte ScrCmd_facilitytrainerbattle @ 0xe6 gScriptCmdTableEnd:: .4byte ScrCmd_nop diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index 900e5da8f8a6..3d31205a508b 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -117,13 +117,6 @@ EventScript_ShowTrainerIntroMsg:: EventScript_DoTrainerBattle:: dotrainerbattle - @ Below battle mode check only needed in FRLG - specialvar VAR_RESULT, GetTrainerBattleMode - goto_if_eq VAR_RESULT, TRAINER_BATTLE_SINGLE, EventScript_EndTrainerBattle - goto_if_eq VAR_RESULT, TRAINER_BATTLE_CONTINUE_SCRIPT, EventScript_EndTrainerBattle - goto_if_eq VAR_RESULT, TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, EventScript_EndTrainerBattle - goto_if_eq VAR_RESULT, TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, EventScript_EndTrainerBattle - goto_if_eq VAR_RESULT, TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, EventScript_EndTrainerBattle EventScript_EndTrainerBattle:: gotobeatenscript releaseall @@ -135,3 +128,66 @@ Std_MsgboxAutoclose:: waitbuttonpress release return + +EventSnippet_Lock:: + lock + faceplayer + setflag FLAG_SAFE_FOLLOWER_MOVEMENT + return + +EventSnippet_StartTrainerApproach:: + selectapproachingtrainer + lockfortrainer + return + +EventSnippet_TrainerApproach:: + special DoTrainerApproach + waitstate + return + +EventSnippet_RevealTrainer:: + applymovement VAR_LAST_TALKED, Movement_RevealTrainer + waitmovement 0 + clearflag FLAG_SAFE_FOLLOWER_MOVEMENT + return + +EventScript_IsTrainerFlagSet:: + specialvar VAR_RESULT, GetTrainerFlag + goto_if_ne VAR_RESULT, FALSE, EventScript_NoNormalTrainerBattle + return + +EventSnippet_PlayTrainerEncounterMusic:: + special PlayTrainerEncounterMusic + return + +EventSnippet_SetTrainerFacingDirection:: + special SetTrainerFacingDirection + return + +EventSnippet_ShowTrainerIntroMsg:: + special ShowTrainerIntroSpeech + waitmessage + waitbuttonpress + return + +EventSnippet_PrepareSecondTrainerApproach:: + special PrepareSecondApproachingTrainer + return + +EventSnippet_GotoPostBattleScript:: + gotopostbattlescript + return + +EventSnippet_DoTrainerBattle:: + dotrainerbattle + return + +EventSnippet_DoRematchTrainerBattle:: + special BattleSetup_StartRematchBattle + waitstate + return + +EventSnippet_EndTrainerBattle:: + gotobeatenscript + releaseall + end diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 04bbe05e5ad4..ab55619f6f7a 100644 --- a/data/scripts/trainer_hill.inc +++ b/data/scripts/trainer_hill.inc @@ -60,7 +60,7 @@ TrainerHill_1F_Movement_SetInvisible:: @ TRAINER_PHILLIP is an actual Trainer on the SS Tidal, but is used as a placeholder here TrainerHill_EventScript_TrainerBattle:: - trainerbattle TRAINER_BATTLE_HILL, TRAINER_PHILLIP, 0, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText + facilitytrainerbattle TRAINER_BATTLE_HILL trainerhill_postbattletext waitmessage waitbuttonpress diff --git a/data/specials.inc b/data/specials.inc index 4d2bea3d33f4..d9c55fb3a328 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -62,7 +62,6 @@ gSpecials:: def_special ObjectEventInteractionWaterBerryTree def_special PlayerHasBerries def_special IsEnigmaBerryValid - def_special GetTrainerBattleMode def_special ShowTrainerIntroSpeech def_special ShowTrainerCantBattleSpeech def_special GetTrainerFlag @@ -531,6 +530,7 @@ gSpecials:: def_special IsLastMonThatKnowsSurf def_special CountPartyAliveNonEggMons def_special TryPrepareSecondApproachingTrainer + def_special PrepareSecondApproachingTrainer def_special RemoveRecordsWindow def_special CloseDeptStoreElevatorWindow def_special TrySetBattleTowerLinkType diff --git a/docs/tutorials/how_to_dynamic_tainer_battle_framework.md b/docs/tutorials/how_to_dynamic_tainer_battle_framework.md new file mode 100644 index 000000000000..05544bded90b --- /dev/null +++ b/docs/tutorials/how_to_dynamic_tainer_battle_framework.md @@ -0,0 +1,122 @@ +# Contents +- [Contents](#contents) +- [Motivation](#motivation) +- [The What](#the-what) +- [Scope](#scope) +- [The How](#the-how) + - [EventSnippets](#eventsnippets) + - [TrainerBattleParameter](#trainerbattleparameter) + - [Script Building](#script-building) +- [Using the framework](#using-the-framework) + - [1. Adding a new Snippet](#1-adding-a-new-snippet) + - [2. Inserting the Snippet](#2-inserting-the-snippet) + +# Motivation +In ~~vanilla~~ pokeemerald-expanded there are a few different trainer battle types such as single, double or rematch battles. Each battle type may also have small variations like continuing a script after the battle, playing the battle music or not showing the intro text for the opponent. Unfortunately each of these variation is defined as their own static battle type in the battle engine leading to: +``` +TRAINER_BATTLE_SINGLE +TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC +TRAINER_BATTLE_CONTINUE_SCRIPT +TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT +``` +and so on (see [here](https://github.com/rh-hideout/pokeemerald-expansion/blob/c3b0f4dd7f75af3394535651c25f7bf861549eb9/include/constants/battle_setup.h#L4-L17)). It is apparent that with this system it is not possible to have a single battle without music and no intro text, which continues a script. At least not without defining a new battle type (and writing all the required setup code for it). This is fine for few battle types with known variations but leads to a quick explosion in complexity when adding new battle types and variations. +To solve this problem this PR attempts to provide a framework that may dynamically builds the trainer battle event script, depending on the provided parameters in the [`trainerbattle`](https://github.com/u8-Salem/pokeemerald/blob/9753c60c963ce306fae5c8c321280e99eaf409f0/asm/macros/event.inc#L687-L707) macro. In other words: the previously statically defined battle types are *inferred* by the parameters given. Additionally the framework should be easy to understand and expand, providing users with the ability to create entirely new **variations** quickly. To illustrate what is easily possible with this system here some examples: + +- display a victory message after battle for some trainers +- make the player run in a circle after being spotted by an opponent +- opponents take a step backwards after showing their intro text + +Lastly this PR attempts to make trainer battle parameters more easily accessible and mutable. This means even after triggering a battle it should be possible to change any of the parameters from outside the initial `trainerbattle` macro. + +# The What +To achieve this goal this PR makes **2** fundamental changes. +1. Dynamically "build" the trainer battle script by pushing script **Snippets** on the global Script Stack when the relevant parameter is provided. To run the finished script, cascade down the stack by running each snippet sequentially. +2. Consolidate (almost) all relevant trainer battle parameters into a struct that lives in **EWRAM**. When reading parameters from a `trainerbattle` macro these are stored in this struct and may be mutated and accessed from anywhere. + +These changes are accompanied by several smaller changes that are outlined a bit in the next section. + +# Scope +Since this is a very intrusive change it is to be expected that several issues arise from this down the line. To limit the impact and make this PR easier to digest trainer battles are separated into the following **groups**: +- normal trainer battles (single/doubles/approaching) +- multi trainer battles (single/double/*wild*) +- facility trainer battles (trainer hill, battle facilities) +- special trainer battles (e-reader/secret base) + +The scope of this PR is then: +- provide the script building framework +- provide the battle parameter struct +- adjust **ALL** battle groups to use the battle parameter struct +- change **only** normal trainer battles to use the script building framework +- make necessary changes to **other** groups to decouple them from normal trainer battles (i.e. trainer hill using `trainerbattle` macro) + +# The How +## EventSnippets +To build the trainer battle script, the individual parts must be provided as [`EventSnippets`](https://github.com/u8-Salem/pokeemerald/blob/e431236a9469fc5c7e47e1dd6e92b7fe8a249493/include/event_scripts.h#L42-L55). `EventSnippets` are no different from normal `EventScripts` but they must end with **`return`** if other scripts are meant to be executed after it. A snippet should contain no more than a single "action", like showing the intro text or play the encounter music. + +## TrainerBattleParameter +The [`TrainerBattleParameter`](https://github.com/u8-Salem/pokeemerald/blob/e431236a9469fc5c7e47e1dd6e92b7fe8a249493/include/battle_setup.h#L20-L43) union lives in **ERWAM** as [`gTrainerBattleParameter`](https://github.com/u8-Salem/pokeemerald/blob/e431236a9469fc5c7e47e1dd6e92b7fe8a249493/src/battle_setup.c#L83). For easier access to the struct that holds the data the macro [`TRAINER_BATTLE_PARAM`](https://github.com/u8-Salem/pokeemerald/blob/e431236a9469fc5c7e47e1dd6e92b7fe8a249493/include/battle_setup.h#L73) is provided. `trainerbattle` requires **ALL** parameters to be provided. Parameters that are not used must be **`0`** (or an alias such as `NULL, OBJ_ID_NONE, TRAINER_NONE`). +`ScrCmd_trainerbattle` will first copy all parameters over to `gTrainerBattleParameter`. + +## Script Building +After the `gTrainerBattleParameter`was initialized with the parameters the scripts is build in [`BattleSetup_ConfigureTrainerBattle`](https://github.com/u8-Salem/pokeemerald/blob/e431236a9469fc5c7e47e1dd6e92b7fe8a249493/src/battle_setup.c#L1089). Here, changes to battle parameters can be made like +```C +if (TRAINER_BATTLE_PARAM.isRematch) +{ + TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); +} +``` + +or Snippets may be pushed onto the stack. + +```C +if (TRAINER_BATTLE_PARAM.playMusicA) +{ + PUSH(EventSnippet_PlayTrainerEncounterMusic); +} +``` + +# Using the framework + +Lets demonstrate how to use the framework by adding a simple message before a trainer battle starts like this \ +![example](script_building_example.gif) + +### 1. Adding a new Snippet + +First we must create a new `EventSnippet` that does the action we want. In this case its a simple `msgbox` but it may be whatever you want. +``` +EventSnippet_PlayerSeen:: + msgbox EventSnippet_Text_GetReady, MSGBOX_AUTOCLOSE + waitmessage + return + +EventSnippet_Text_GetReady: + .string "I was seen!\l" + .string "Lets get ready to fight.$" +``` +in `event_scripts.h`: +``` +extern const u8 EventSnippet_PlayerSeen[]; +``` + +### 2. Inserting the Snippet +Now we need to push our Snippet onto the Stack at the right time. +Since I want this only to apply for **approaching** trainers I add **`PUSH(EventSnippet_PlayerSeen)`** to `BattleSetup_ConfigureTrainerBattleApproachingTrainer` in `battle_setup.c`: +```C +const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) +{ + if (TRAINER_BATTLE_PARAM.playMusicA) + { + PUSH(EventSnippet_PlayTrainerEncounterMusic); + } + + PUSH(EventSnippet_PlayerSeen); + PUSH(EventSnippet_TrainerApproach); + + if (TRAINER_BATTLE_PARAM.introTextA != NULL) + { + PUSH(EventSnippet_ShowTrainerIntroMsg); + } + ... +} +``` +The order in which snippets are pushed onto the stack is important here. I want my message to show **before** the trainers approach, so I need to push it before `PUSH(EventSnippet_TrainerApproach)`. \ No newline at end of file diff --git a/docs/tutorials/script_building_example.gif b/docs/tutorials/script_building_example.gif new file mode 100644 index 000000000000..9afb0a81cde4 Binary files /dev/null and b/docs/tutorials/script_building_example.gif differ diff --git a/include/battle_setup.h b/include/battle_setup.h index a2009eea4122..ea0f8426359f 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -4,6 +4,7 @@ #include "gym_leader_rematch.h" #define REMATCHES_COUNT 5 +#define MAX_STACK_SIZE 20 struct RematchTrainer { @@ -12,10 +13,69 @@ struct RematchTrainer u16 mapNum; }; +/* +the layout of the first byte can be confusing here +isDoubleBattle is the least lsb. msb is in the padding. +*/ +typedef union PACKED TrainerBattleParameter +{ + struct PACKED _TrainerBattleParameter + { + u8 isDoubleBattle:1; + u8 isRematch:1; + u8 playMusicA:1; + u8 playMusicB:1; + u8 padding:4; + u8 objEventLocalIdA; + u16 battleOpponentA; + u8* introTextA; + u8* defeatTextA; + u8* battleScriptRetAddrA; + u8 objEventLocalIdB; + u16 battleOpponentB; + u8* introTextB; + u8* defeatTextB; + u8* battleScriptRetAddrB; + u8* victoryText; + u8* cannotBattleText; + } params; + u8 data[sizeof(struct _TrainerBattleParameter)]; +} TrainerBattleParameter; + +/* + to use with old multi battle system + used instead of TRAINER_BATTLE_SET_TRAINER_A/B modes of trainerbattle macro +*/ +typedef union PACKED MultiTrainerBattleParameter +{ + struct PACKED _MultiTrainerBattleParameter + { + u16 battleOpponentA; + u8* defeatTextA; + u16 battleOpponentB; + u8* defeatTextB; + } params; + u8 data[sizeof(struct _MultiTrainerBattleParameter)]; +} MultiTrainerBattleParameter; + +#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\npadding: %d\nlocalIdA: %d\ntrainerA: %d\nintroA: %x\ndefeatA: %x\neventA: %x\nlocalIdB: %d\ntrainerB: %d\nintroB: %x\ndefeatB: %x\neventB: %x\nvictory: %x\nnotBattle:%x\n", \ + battleParameter->params.isDoubleBattle, battleParameter->params.playMusicA, battleParameter->params.playMusicB, battleParameter->params.isRematch, battleParameter->params.padding, \ + battleParameter->params.objEventLocalIdA, battleParameter->params.battleOpponentA, battleParameter->params.introTextA, battleParameter->params.defeatTextA, battleParameter->params.battleScriptRetAddrA, \ + battleParameter->params.objEventLocalIdB, battleParameter->params.battleOpponentB, battleParameter->params.introTextB, battleParameter->params.defeatTextB, battleParameter->params.battleScriptRetAddrB, \ + battleParameter->params.victoryText, battleParameter->params.cannotBattleText) + +typedef struct TrainerBattleScriptStack +{ + const u8* stack[MAX_STACK_SIZE]; + s8 stackPtr; +} TrainerBattleScriptStack; + +#define TRAINER_BATTLE_PARAM gTrainerBattleParameter.params + extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; -extern u16 gTrainerBattleOpponent_A; -extern u16 gTrainerBattleOpponent_B; +extern TrainerBattleParameter gTrainerBattleParameter; +extern bool16 gHideCancelOptionOnPartySelect; extern u16 gPartnerTrainerId; void BattleSetup_StartWildBattle(void); @@ -35,14 +95,14 @@ u8 GetTrainerBattleTransition(void); u8 GetSpecialBattleTransition(s32 id); void ChooseStarter(void); void ResetTrainerOpponentIds(void); -void SetMapVarsToTrainer(void); -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data); +void SetMapVarsToTrainerA(void); +void SetMapVarsToTrainerB(void); +const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching); void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript); void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript); void SetUpTwoTrainersBattle(void); bool32 GetTrainerFlagFromScriptPointer(const u8 *data); void SetTrainerFacingDirection(void); -u8 GetTrainerBattleMode(void); bool8 GetTrainerFlag(void); bool8 HasTrainerBeenFought(u16 trainerId); void SetTrainerFlag(u16 trainerId); @@ -51,6 +111,7 @@ void BattleSetup_StartTrainerBattle(void); void BattleSetup_StartRematchBattle(void); void ShowTrainerIntroSpeech(void); const u8 *BattleSetup_GetScriptAddrAfterBattle(void); +void BattleSetup_SetScriptAddrAfterBattle(const u8* ptr); const u8 *BattleSetup_GetTrainerPostBattleScript(void); void ShowTrainerCantBattleSpeech(void); void PlayTrainerEncounterMusic(void); @@ -67,11 +128,18 @@ bool8 ShouldTryRematchBattle(void); bool8 IsTrainerReadyForRematch(void); void ShouldTryGetTrainerScript(void); u16 CountBattledRematchTeams(u16 trainerId); +void TrainerBattleLoadArgs(const u8* data); +void TrainerBattleLoadArgsTrainerA(const u8* data); +void TrainerBattleLoadArgsTrainerB(const u8* data); +void TrainerBattleLoadArgsSecondTrainer(const u8* data); +void MultiTrainerBattleLoadArgs(const u8* data); +void InitTrainerBattleVariables(void); void DoStandardWildBattle_Debug(void); void BattleSetup_StartTrainerBattle_Debug(void); s32 TrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId); s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId); u16 GetRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId); +const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 type, const u8* scriptEndPtr); #endif // GUARD_BATTLE_SETUP_H diff --git a/include/config/general.h b/include/config/general.h index cff1432bb737..bd34106832c5 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -6,7 +6,7 @@ // still has them in the ROM. This is because the developers forgot // to define NDEBUG before release, however this has been changed as // Ruby's actual debug build does not use the AGBPrint features. -#define NDEBUG +// #define NDEBUG // To enable printf debugging, comment out "#define NDEBUG". This allows // the various AGBPrint functions to be used. (See include/gba/isagbprint.h). diff --git a/include/constants/battle.h b/include/constants/battle.h index eeccd8314417..5ff0d56d63fa 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -86,7 +86,7 @@ #define WILD_DOUBLE_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER)))) #define RECORDED_WILD_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_RECORDED) && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER))) -#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gTrainerBattleOpponent_B == 0xFFFF)) +#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.battleOpponentB == 0xFFFF)) #define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER) // Battle Outcome defines diff --git a/include/constants/vars.h b/include/constants/vars.h index e79919c329f1..81d5a19a4743 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -301,7 +301,7 @@ #define VAR_MON_BOX_ID 0x8012 #define VAR_MON_BOX_POS 0x8013 #define VAR_UNUSED_0x8014 0x8014 -#define VAR_TRAINER_BATTLE_OPPONENT_A 0x8015 // Alias of gTrainerBattleOpponent_A +#define VAR_TRAINER_BATTLE_OPPONENT_A 0x8015 // Alias of TRAINER_BATTLE_PARAM.battleOpponentA #define SPECIAL_VARS_END 0x8015 diff --git a/include/event_scripts.h b/include/event_scripts.h index 133d9fa98bb9..245ad113309f 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -36,6 +36,23 @@ extern const u8 EventScript_TryDoDoubleTrainerBattle[]; extern const u8 EventScript_TryDoNormalTrainerBattle[]; extern const u8 EventScript_TryDoDoubleRematchBattle[]; extern const u8 EventScript_TryDoRematchBattle[]; +extern const u8 EventScript_ShowTrainerIntroMsg[]; +extern const u8 EventScript_NotEnoughMonsForDoubleBattle[]; + +extern const u8 EventSnippet_Lock[]; +extern const u8 EventSnippet_StartTrainerApproach[]; +extern const u8 EventSnippet_TryDoNormalTrainerBattle[]; +extern const u8 EventSnippet_RevealTrainer[]; +extern const u8 EventSnippet_GetTrainerFlag[]; +extern const u8 EventSnippet_PlayTrainerEncounterMusic[]; +extern const u8 EventSnippet_SetTrainerFacingDirection[]; +extern const u8 EventSnippet_TrainerApproach[]; +extern const u8 EventSnippet_PrepareSecondTrainerApproach[]; +extern const u8 EventSnippet_ShowTrainerIntroMsg[]; +extern const u8 EventSnippet_GotoPostBattleScript[]; +extern const u8 EventSnippet_DoTrainerBattle[]; +extern const u8 EventSnippet_DoRematchTrainerBattle[]; +extern const u8 EventSnippet_EndTrainerBattle[]; extern const u8 BerryTreeScript[]; diff --git a/include/global.h b/include/global.h index 3e5e984547c5..94e3db315a73 100644 --- a/include/global.h +++ b/include/global.h @@ -7,6 +7,7 @@ #include "gba/gba.h" #include "fpmath.h" #include "metaprogram.h" +#include "stack.h" #include "constants/global.h" #include "constants/flags.h" #include "constants/vars.h" diff --git a/include/script.h b/include/script.h index 1f3c4f7afb95..37fe2cac7f33 100644 --- a/include/script.h +++ b/include/script.h @@ -21,11 +21,33 @@ struct ScriptContext #define ScriptReadByte(ctx) (*(ctx->scriptPtr++)) +#define DebugPrintScriptStack \ +do { \ + u8 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______ScriptStack________"); \ + for (i = ctx->stackDepth; i > 0; i--) { \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i-1, ctx->stack[i-1]); \ + } \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______StackFloor_________"); \ +} while(0); + +#define DebugPrintGlobalScriptStack \ +do { \ + u8 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______GlobalScriptStack________"); \ + for (i = sGlobalScriptContext.stackDepth; i > 0; i--) { \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i-1, sGlobalScriptContext.stack[i-1]); \ + } \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______GlobalStackFloor_________"); \ +} while(0); + void InitScriptContext(struct ScriptContext *ctx, void *cmdTable, void *cmdTableEnd); u8 SetupBytecodeScript(struct ScriptContext *ctx, const u8 *ptr); void SetupNativeScript(struct ScriptContext *ctx, bool8 (*ptr)(void)); void StopScript(struct ScriptContext *ctx); bool8 RunScriptCommand(struct ScriptContext *ctx); +bool8 ScriptPush(struct ScriptContext *ctx, const u8 *ptr); +const u8 *ScriptPop(struct ScriptContext *ctx); void ScriptJump(struct ScriptContext *ctx, const u8 *ptr); void ScriptCall(struct ScriptContext *ctx, const u8 *ptr); void ScriptReturn(struct ScriptContext *ctx); @@ -41,6 +63,7 @@ bool8 ScriptContext_RunScript(void); void ScriptContext_SetupScript(const u8 *ptr); void ScriptContext_Stop(void); void ScriptContext_Enable(void); +bool32 ScriptContext_PushFromStack(PtrStack *stack); void RunScriptImmediately(const u8 *ptr); u8 *MapHeaderGetScriptTable(u8 tag); void MapHeaderRunScriptType(u8 tag); diff --git a/include/script_pokemon_util.h b/include/script_pokemon_util.h index 6508295a2dcd..aa50e3ba6371 100644 --- a/include/script_pokemon_util.h +++ b/include/script_pokemon_util.h @@ -12,5 +12,6 @@ void Script_GetChosenMonOffensiveEVs(void); void Script_GetChosenMonDefensiveEVs(void); void Script_GetChosenMonOffensiveIVs(void); void Script_GetChosenMonDefensiveIVs(void); +u8 HasEnoughMonsForDoubleBattle2(void); #endif // GUARD_SCRIPT_POKEMON_UTIL_H diff --git a/include/stack.h b/include/stack.h new file mode 100644 index 000000000000..cf729774f3b7 --- /dev/null +++ b/include/stack.h @@ -0,0 +1,28 @@ +#ifndef GUARD_STACK_H +#define GUARD_STACK_H + +#define STACK_SIZE 0xFF + +typedef struct PtrStack +{ + void* stack[STACK_SIZE]; + s32 stackPtr; +} PtrStack; + +#define DebugPrintStack(s) \ +do { \ + s16 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______StackTop______"); \ + for (i = s->stackPtr; i > -1; i--) { \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, s->stack[i]); \ + } \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______StackFloor______"); \ +} while(0) + +void PtrStackInit(PtrStack* stack); +void* PtrStackPop(PtrStack* stack); +bool32 PtrStackPush(PtrStack* stack, void* ptr); +const u8* PtrStackPopU8(PtrStack *stack); +bool32 PtrStackPushU8(PtrStack *stack, const u8* ptr); + +#endif // GUARD_STACK_H diff --git a/include/trainer_see.h b/include/trainer_see.h index 5518a91761c2..6764e5fd33c0 100644 --- a/include/trainer_see.h +++ b/include/trainer_see.h @@ -20,6 +20,8 @@ bool8 CheckForTrainersWantingBattle(void); void SetBuriedTrainerMovement(struct ObjectEvent *var); void DoTrainerApproach(void); void TryPrepareSecondApproachingTrainer(void); +void PrepareSecondApproachingTrainer(void); +bool32 TryPrepareSecondApproachingTrainer2(void); u8 FldEff_ExclamationMarkIcon(void); u8 FldEff_QuestionMarkIcon(void); u8 FldEff_HeartIcon(void); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 828b7b7c94aa..aa9e1a62e6ab 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -100,7 +100,7 @@ void BattleAI_SetupItems(void) { s32 i; u8 *data = (u8 *)BATTLE_HISTORY; - const u16 *items = GetTrainerItemsFromId(gTrainerBattleOpponent_A); + const u16 *items = GetTrainerItemsFromId(TRAINER_BATTLE_PARAM.battleOpponentA); for (i = 0; i < sizeof(struct BattleHistory); i++) data[i] = 0; @@ -211,9 +211,9 @@ void BattleAI_SetupFlags(void) } else { - AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(gTrainerBattleOpponent_A); - if (gTrainerBattleOpponent_B != 0) - AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(gTrainerBattleOpponent_B); + AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(TRAINER_BATTLE_PARAM.battleOpponentA); + if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) + AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(TRAINER_BATTLE_PARAM.battleOpponentB); else AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT]; } diff --git a/src/battle_arena.c b/src/battle_arena.c index ff406a37df6f..d9608d63222a 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -473,7 +473,7 @@ static void InitArenaChallenge(void) gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode] = 0; SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetArenaData(void) @@ -563,7 +563,7 @@ static void GiveArenaPrize(void) static void BufferArenaOpponentName(void) { - GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar1, TRAINER_BATTLE_PARAM.battleOpponentA); } void DrawArenaRefereeTextBox(void) diff --git a/src/battle_bg.c b/src/battle_bg.c index 328f990653e0..c364be5079d2 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -806,7 +806,7 @@ void DrawMainBattleBackground(void) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); @@ -1207,7 +1207,7 @@ void DrawBattleEntryBackground(void) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); @@ -1272,7 +1272,7 @@ bool8 LoadChosenBattleElement(u8 caseId) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); @@ -1334,7 +1334,7 @@ bool8 LoadChosenBattleElement(u8 caseId) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); @@ -1396,7 +1396,7 @@ bool8 LoadChosenBattleElement(u8 caseId) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (trainerClass == TRAINER_CLASS_LEADER) { LoadCompressedPalette(gBattleTerrainPalette_BuildingLeader, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 7aeefa54b6a6..a17e08fad753 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -405,9 +405,9 @@ static void LinkOpponentHandleDrawTrainerPic(u32 battler) if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) { if (battler == B_POSITION_OPPONENT_LEFT) - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { @@ -436,7 +436,7 @@ static void LinkOpponentHandleDrawTrainerPic(u32 battler) else { xPos = 176; - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) { trainerPicId = GetUnionRoomTrainerPic(); } @@ -470,9 +470,9 @@ static void LinkOpponentHandleTrainerSlide(u32 battler) u32 trainerPicId; if (battler == B_POSITION_OPPONENT_LEFT) - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); BtlController_HandleTrainerSlide(battler, trainerPicId); LinkOpponentBufferExecCompleted(battler); // Possibly a bug, because execution should be completed after the slide in finishes. See Controller_WaitForTrainerPic. diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 898a59c2ee7f..9c64e3f66970 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -437,7 +437,7 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) { trainerPicId = GetSecretBaseTrainerPicIndex(); } - else if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) { trainerPicId = GetFrontierBrainTrainerPicIndex(); } @@ -446,13 +446,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId == 1) - trainerPicId = GetTrainerHillTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetTrainerHillTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { - trainerPicId = GetTrainerHillTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); } } else if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) @@ -460,13 +460,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TOWER_LINK_MULTI)) { if (battlerId == 1) - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); } } else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) @@ -476,13 +476,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId != 1) - trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_B); + trainerPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.battleOpponentB); else - trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.battleOpponentA); } else { - trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.battleOpponentA); } return trainerPicId; diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index afd56a9faf42..8855a736b673 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -413,9 +413,9 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) { if (battler == B_POSITION_OPPONENT_LEFT) - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { @@ -425,7 +425,7 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) else { xPos = 176; - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) { trainerPicId = GetUnionRoomTrainerPic(); } diff --git a/src/battle_dome.c b/src/battle_dome.c index 19c508652342..ed6cf9831a3c 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -1782,7 +1782,7 @@ static void InitDomeChallenge(void) gSaveBlock2Ptr->frontier.domeWinStreaks[battleMode][lvlMode] = 0; SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetDomeData(void) @@ -2182,13 +2182,13 @@ static void BufferDomeRoundText(void) static void BufferDomeOpponentName(void) { StringCopy(gStringVar1, gRoundsStringTable[gSaveBlock2Ptr->frontier.curChallengeBattleNum]); - CopyDomeTrainerName(gStringVar2, gTrainerBattleOpponent_A); + CopyDomeTrainerName(gStringVar2, TRAINER_BATTLE_PARAM.battleOpponentA); } static void InitDomeOpponentParty(void) { CalculatePlayerPartyCount(); - CreateDomeOpponentMons(TrainerIdToTournamentId(gTrainerBattleOpponent_A)); + CreateDomeOpponentMons(TrainerIdToTournamentId(TRAINER_BATTLE_PARAM.battleOpponentA)); } static void CreateDomeOpponentMon(u8 monPartyId, u16 tournamentTrainerId, u8 tournamentMonId, u32 otId) @@ -2577,7 +2577,7 @@ static int TournamentIdOfOpponent(int roundId, int trainerId) static void SetDomeOpponentId(void) { - gTrainerBattleOpponent_A = TrainerIdOfPlayerOpponent(); + TRAINER_BATTLE_PARAM.battleOpponentA = TrainerIdOfPlayerOpponent(); } // While not an issue in-game, this will overflow if called after the player's opponent for the current round has been eliminated @@ -2588,7 +2588,7 @@ static u16 TrainerIdOfPlayerOpponent(void) static void SetDomeOpponentGraphicsId(void) { - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void SaveDomeChallenge(void) @@ -5063,9 +5063,9 @@ static void ResolveDomeRoundWinners(void) if (gSpecialVar_0x8005 == DOME_PLAYER_WON_MATCH) { - DOME_TRAINERS[TrainerIdToTournamentId(gTrainerBattleOpponent_A)].isEliminated = TRUE; - DOME_TRAINERS[TrainerIdToTournamentId(gTrainerBattleOpponent_A)].eliminatedAt = gSaveBlock2Ptr->frontier.curChallengeBattleNum; - gSaveBlock2Ptr->frontier.domeWinningMoves[TrainerIdToTournamentId(gTrainerBattleOpponent_A)] = gBattleResults.lastUsedMovePlayer; + DOME_TRAINERS[TrainerIdToTournamentId(TRAINER_BATTLE_PARAM.battleOpponentA)].isEliminated = TRUE; + DOME_TRAINERS[TrainerIdToTournamentId(TRAINER_BATTLE_PARAM.battleOpponentA)].eliminatedAt = gSaveBlock2Ptr->frontier.curChallengeBattleNum; + gSaveBlock2Ptr->frontier.domeWinningMoves[TrainerIdToTournamentId(TRAINER_BATTLE_PARAM.battleOpponentA)] = gBattleResults.lastUsedMovePlayer; // If the player's match was the final one, no NPC vs NPC matches to decide if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < DOME_FINAL) @@ -5693,7 +5693,7 @@ static void ReduceDomePlayerPartyToSelectedMons(void) static void GetPlayerSeededBeforeOpponent(void) { // A higher tournament ID is a worse seed - if (TrainerIdToTournamentId(gTrainerBattleOpponent_A) > TrainerIdToTournamentId(TRAINER_PLAYER)) + if (TrainerIdToTournamentId(TRAINER_BATTLE_PARAM.battleOpponentA) > TrainerIdToTournamentId(TRAINER_PLAYER)) gSpecialVar_Result = 1; else gSpecialVar_Result = 2; diff --git a/src/battle_factory.c b/src/battle_factory.c index 8edd9a2ddff4..e44f80662119 100644 --- a/src/battle_factory.c +++ b/src/battle_factory.c @@ -218,7 +218,7 @@ static void InitFactoryChallenge(void) gFrontierTempParty[i] = 0xFFFF; SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetBattleFactoryData(void) @@ -325,7 +325,7 @@ static void GenerateOpponentMons(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_A = trainerId; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < FRONTIER_STAGES_PER_CHALLENGE - 1) gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = trainerId; @@ -379,7 +379,7 @@ static void GenerateOpponentMons(void) static void SetOpponentGfxVar(void) { - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void SetRentalsToOpponentParty(void) @@ -830,7 +830,7 @@ u32 GetAiScriptsInBattleFactory(void) int battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE); int challengeNum = gSaveBlock2Ptr->frontier.factoryWinStreaks[battleMode][lvlMode] / FRONTIER_STAGES_PER_CHALLENGE; - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY; else if (challengeNum < 2) return 0; diff --git a/src/battle_gimmick.c b/src/battle_gimmick.c index 057619aec1fe..ecb729b6551c 100644 --- a/src/battle_gimmick.c +++ b/src/battle_gimmick.c @@ -80,7 +80,7 @@ bool32 ShouldTrainerBattlerUseGimmick(u32 battler, enum Gimmick gimmick) else { bool32 isSecondTrainer = (GetBattlerPosition(battler) == B_POSITION_OPPONENT_RIGHT) && (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && !BATTLE_TWO_VS_ONE_OPPONENT; - u16 trainerId = isSecondTrainer ? gTrainerBattleOpponent_B : gTrainerBattleOpponent_A; + u16 trainerId = isSecondTrainer ? TRAINER_BATTLE_PARAM.battleOpponentB : TRAINER_BATTLE_PARAM.battleOpponentA; const struct TrainerMon *mon = &GetTrainerPartyFromId(trainerId)[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]]; if (gimmick == GIMMICK_TERA && mon->teraType != TYPE_NONE) diff --git a/src/battle_main.c b/src/battle_main.c index 1938cef20c43..8fadebae6a53 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -525,7 +525,7 @@ static void CB2_InitBattleInternal(void) | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL))) { - gBattleTypeFlags |= (IsTrainerDoubleBattle(gTrainerBattleOpponent_A) ? BATTLE_TYPE_DOUBLE : 0); + gBattleTypeFlags |= (IsTrainerDoubleBattle(TRAINER_BATTLE_PARAM.battleOpponentA) ? BATTLE_TYPE_DOUBLE : 0); } InitBattleBgsVideo(); @@ -552,9 +552,9 @@ static void CB2_InitBattleInternal(void) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED))) { - CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A, TRUE); + CreateNPCTrainerParty(&gEnemyParty[0], TRAINER_BATTLE_PARAM.battleOpponentA, TRUE); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) - CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], gTrainerBattleOpponent_B, FALSE); + CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], TRAINER_BATTLE_PARAM.battleOpponentB, FALSE); SetWildMonHeldItem(); CalculateEnemyPartyCount(); } @@ -861,7 +861,7 @@ static void CB2_HandleStartBattle(void) BufferPartyVsScreenHealth_AtStart(); SetPlayerBerryDataInBattleStruct(); - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) { gLinkPlayers[0].id = 0; gLinkPlayers[1].id = 1; @@ -1066,11 +1066,11 @@ static void CB2_HandleStartMultiPartnerBattle(void) gLinkPlayers[1].id = 2; gLinkPlayers[2].id = 1; gLinkPlayers[3].id = 3; - GetFrontierTrainerName(gLinkPlayers[2].name, gTrainerBattleOpponent_A); - GetFrontierTrainerName(gLinkPlayers[3].name, gTrainerBattleOpponent_B); - GetBattleTowerTrainerLanguage(&language, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gLinkPlayers[2].name, TRAINER_BATTLE_PARAM.battleOpponentA); + GetFrontierTrainerName(gLinkPlayers[3].name, TRAINER_BATTLE_PARAM.battleOpponentB); + GetBattleTowerTrainerLanguage(&language, TRAINER_BATTLE_PARAM.battleOpponentA); gLinkPlayers[2].language = language; - GetBattleTowerTrainerLanguage(&language, gTrainerBattleOpponent_B); + GetBattleTowerTrainerLanguage(&language, TRAINER_BATTLE_PARAM.battleOpponentB); gLinkPlayers[3].language = language; if (IsLinkTaskFinished()) @@ -1721,7 +1721,7 @@ static void CB2_HandleStartMultiBattle(void) SetMainCallback2(BattleMainCB2); if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_LINK_OPPONENT; gBattleTypeFlags |= BATTLE_TYPE_LINK_IN_BATTLE; } } @@ -3796,14 +3796,14 @@ static void DoBattleIntro(void) // Try to set a status to start the battle with gBattleStruct->startingStatus = 0; - if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetTrainerStartingStatusFromId(gTrainerBattleOpponent_B)) + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentB)) { - gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_B); + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentB); gBattleStruct->startingStatusTimer = 0; // infinite } - else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A)) + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentA)) { - gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A); + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentA); gBattleStruct->startingStatusTimer = 0; // infinite } else if (B_VAR_STARTING_STATUS != 0) @@ -5461,7 +5461,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_FrontierTrainerBattleWon; - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) PlayBGM(MUS_VICTORY_GYM_LEADER); else PlayBGM(MUS_VICTORY_TRAINER); @@ -5471,7 +5471,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon; - switch (GetTrainerClassFromId(gTrainerBattleOpponent_A)) + switch (GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA)) { case TRAINER_CLASS_ELITE_FOUR: case TRAINER_CLASS_CHAMPION: diff --git a/src/battle_message.c b/src/battle_message.c index de02a27ea3c5..ea027b8f7b53 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2093,7 +2093,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1WantsToBattle; else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) stringPtr = sText_LinkTrainerWantsToBattlePause; @@ -2165,7 +2165,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK))) stringPtr = sText_Trainer1SentOutPkmn; - else if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1SentOutPkmn; else stringPtr = sText_LinkTrainerSentOutPkmn; @@ -2186,7 +2186,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (gTrainerBattleOpponent_A == TRAINER_LINK_OPPONENT || gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_LINK_OPPONENT || gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) stringPtr = sText_LinkTrainer2WithdrewPkmn; @@ -2226,7 +2226,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) stringPtr = sText_LinkTrainerMultiSentOutPkmn; - else if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1SentOutPkmn2; else stringPtr = sText_LinkTrainerSentOutPkmn2; @@ -2294,7 +2294,7 @@ void BufferStringBattle(u16 stringID, u32 battler) break; } } - else if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) { switch (gBattleTextBuff1[0]) { @@ -2496,13 +2496,13 @@ static const u8 *BattleStringGetOpponentName(u8 *text, u8 multiplayerId, u8 batt switch (GetBattlerPosition(battler)) { case B_POSITION_OPPONENT_LEFT: - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_A, text, multiplayerId, battler); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA, text, multiplayerId, battler); break; case B_POSITION_OPPONENT_RIGHT: if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI) && !BATTLE_TWO_VS_ONE_OPPONENT) - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_B, text, multiplayerId, battler); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB, text, multiplayerId, battler); else - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_A, text, multiplayerId, battler); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA, text, multiplayerId, battler); break; } @@ -2794,14 +2794,14 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) toCpy = gAbilitiesInfo[sBattlerAbilities[gEffectBattler]].name; break; case B_TXT_TRAINER1_CLASS: // trainer class name - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; case B_TXT_TRAINER1_NAME: // trainer1 name - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_A, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); break; case B_TXT_TRAINER1_NAME_WITH_CLASS: // trainer1 name with trainer class toCpy = textStart; - classString = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + classString = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); while (classString[classLength] != EOS) { textStart[classLength] = classString[classLength]; @@ -2809,7 +2809,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) } textStart[classLength] = CHAR_SPACE; textStart += classLength + 1; - nameString = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_A, textStart, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); + nameString = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA, textStart, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); if (nameString != textStart) { while (nameString[nameLength] != EOS) @@ -2841,12 +2841,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) case B_TXT_TRAINER1_LOSE_TEXT: // trainerA lose text if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, gTrainerBattleOpponent_A); + CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, gTrainerBattleOpponent_A); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } else @@ -2857,12 +2857,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) case B_TXT_TRAINER1_WIN_TEXT: // trainerA win text if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, gTrainerBattleOpponent_A); + CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, gTrainerBattleOpponent_A); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } break; @@ -2931,14 +2931,14 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) toCpy = sText_FoePkmnPrefix4; break; case B_TXT_TRAINER2_CLASS: - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_B); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB); break; case B_TXT_TRAINER2_NAME: - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_B, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)); break; case B_TXT_TRAINER2_NAME_WITH_CLASS: toCpy = textStart; - classString = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_B); + classString = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB); while (classString[classLength] != EOS) { textStart[classLength] = classString[classLength]; @@ -2946,7 +2946,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) } textStart[classLength] = CHAR_SPACE; textStart += classLength + 1; - nameString = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_B, textStart, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)); + nameString = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB, textStart, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)); if (nameString != textStart) { while (nameString[nameLength] != EOS) @@ -2960,12 +2960,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) case B_TXT_TRAINER2_LOSE_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, gTrainerBattleOpponent_B); + CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, gTrainerBattleOpponent_B); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } else @@ -2976,12 +2976,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) case B_TXT_TRAINER2_WIN_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, gTrainerBattleOpponent_B); + CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, gTrainerBattleOpponent_B); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } break; @@ -3023,13 +3023,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) toCpy = gTrainerClasses[GetFrontierOpponentClass(gPartnerTrainerId)].name; break; case B_POSITION_OPPONENT_LEFT: - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; case B_POSITION_OPPONENT_RIGHT: if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_B); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB); else - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; } break; @@ -3049,13 +3049,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) classString = gTrainerClasses[GetFrontierOpponentClass(gPartnerTrainerId)].name; break; case B_POSITION_OPPONENT_LEFT: - classString = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + classString = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; case B_POSITION_OPPONENT_RIGHT: if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) - classString = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_B); + classString = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB); else - classString = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + classString = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; } classLength = 0; @@ -3651,19 +3651,19 @@ u32 ShouldDoTrainerSlide(u32 battler, u32 which) if (gBattlerPartyIndexes[battler] >= 3) { firstId = 3, lastId = PARTY_SIZE; - trainerId = gTrainerBattleOpponent_B; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentB; retValue = 2; } else { firstId = 0, lastId = 3; - trainerId = gTrainerBattleOpponent_A; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; } } else { firstId = 0, lastId = PARTY_SIZE; - trainerId = gTrainerBattleOpponent_A; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; } enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(trainerId); diff --git a/src/battle_palace.c b/src/battle_palace.c index fdcb8d3903a8..661648b9ed01 100644 --- a/src/battle_palace.c +++ b/src/battle_palace.c @@ -94,7 +94,7 @@ static void InitPalaceChallenge(void) gSaveBlock2Ptr->frontier.palaceWinStreaks[battleMode][lvlMode] = 0; SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetPalaceData(void) @@ -153,14 +153,14 @@ static void GetPalaceCommentId(void) static void SetPalaceOpponent(void) { - gTrainerBattleOpponent_A = 5 *(Random() % 255) / 64u; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = 5 *(Random() % 255) / 64u; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void BufferOpponentIntroSpeech(void) { - if (gTrainerBattleOpponent_A < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].speechBefore); } static void IncrementPalaceStreak(void) diff --git a/src/battle_pike.c b/src/battle_pike.c index 3ce3cd443a88..c10b3f55d6bc 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -1403,11 +1403,11 @@ static void PrepareOneTrainer(bool8 difficult) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1); - gTrainerBattleOpponent_A = trainerId; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; gFacilityTrainers = gBattleFrontierTrainers; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < NUM_PIKE_ROOMS) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = gTrainerBattleOpponent_A; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = TRAINER_BATTLE_PARAM.battleOpponentA; } static void PrepareTwoTrainers(void) @@ -1429,10 +1429,10 @@ static void PrepareTwoTrainers(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1); - gTrainerBattleOpponent_A = trainerId; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum <= NUM_PIKE_ROOMS) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = gTrainerBattleOpponent_A; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = TRAINER_BATTLE_PARAM.battleOpponentA; do { @@ -1445,10 +1445,10 @@ static void PrepareTwoTrainers(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_B = trainerId; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1); + TRAINER_BATTLE_PARAM.battleOpponentB = trainerId; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentB, 1); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < NUM_PIKE_ROOMS) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 2] = gTrainerBattleOpponent_B; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 2] = TRAINER_BATTLE_PARAM.battleOpponentB; } static void ClearPikeTrainerIds(void) @@ -1463,13 +1463,13 @@ static void BufferTrainerIntro(void) { if (gSpecialVar_0x8005 == 0) { - if (gTrainerBattleOpponent_A < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].speechBefore); } else if (gSpecialVar_0x8005 == 1) { - if (gTrainerBattleOpponent_B < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_B].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentB < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentB].speechBefore); } } @@ -1615,7 +1615,7 @@ static void InitPikeChallenge(void) if (!(gSaveBlock2Ptr->frontier.winStreakActiveFlags & sWinStreakFlags[lvlMode])) gSaveBlock2Ptr->frontier.pikeWinStreaks[lvlMode] = 0; - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; gBattleOutcome = 0; } diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index a184c9160f1c..344f70004585 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -864,7 +864,7 @@ static void InitPyramidChallenge(void) } InitBattlePyramidBagCursorPosition(); - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; gBattleOutcome = 0; } @@ -1324,11 +1324,11 @@ bool8 GetBattlePyramidTrainerFlag(u8 eventId) void MarkApproachingPyramidTrainersAsBattled(void) { - MarkPyramidTrainerAsBattled(gTrainerBattleOpponent_A); + MarkPyramidTrainerAsBattled(TRAINER_BATTLE_PARAM.battleOpponentA); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { gSelectedObjectEvent = GetChosenApproachingTrainerObjectEventId(1); - MarkPyramidTrainerAsBattled(gTrainerBattleOpponent_B); + MarkPyramidTrainerAsBattled(TRAINER_BATTLE_PARAM.battleOpponentB); } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b08b53a0441a..3843b30264b0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8317,9 +8317,9 @@ static void Cmd_getmoneyreward(void) if (gBattleOutcome == B_OUTCOME_WON) { - money = GetTrainerMoneyToGive(gTrainerBattleOpponent_A); + money = GetTrainerMoneyToGive(TRAINER_BATTLE_PARAM.battleOpponentA); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - money += GetTrainerMoneyToGive(gTrainerBattleOpponent_B); + money += GetTrainerMoneyToGive(TRAINER_BATTLE_PARAM.battleOpponentB); AddMoney(&gSaveBlock1Ptr->money, money); } else diff --git a/src/battle_setup.c b/src/battle_setup.c index 0c13fcdd09ca..deee6f85f988 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -57,22 +57,6 @@ enum { TRANSITION_TYPE_WATER, }; -enum { - TRAINER_PARAM_LOAD_VAL_8BIT, - TRAINER_PARAM_LOAD_VAL_16BIT, - TRAINER_PARAM_LOAD_VAL_32BIT, - TRAINER_PARAM_CLEAR_VAL_8BIT, - TRAINER_PARAM_CLEAR_VAL_16BIT, - TRAINER_PARAM_CLEAR_VAL_32BIT, - TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR, -}; - -struct TrainerBattleParameter -{ - void *varPtr; - u8 ptrType; -}; - // this file's functions static void DoBattlePikeWildBattle(void); static void DoSafariBattle(void); @@ -96,20 +80,9 @@ static void HandleRematchVarsOnBattleEnd(void); static const u8 *GetIntroSpeechOfApproachingTrainer(void); static const u8 *GetTrainerCantBattleSpeech(void); -EWRAM_DATA static u16 sTrainerBattleMode = 0; -EWRAM_DATA u16 gTrainerBattleOpponent_A = 0; -EWRAM_DATA u16 gTrainerBattleOpponent_B = 0; +EWRAM_DATA TrainerBattleParameter gTrainerBattleParameter = {0}; EWRAM_DATA u16 gPartnerTrainerId = 0; -EWRAM_DATA static u16 sTrainerObjectEventLocalId = 0; -EWRAM_DATA static u8 *sTrainerAIntroSpeech = NULL; -EWRAM_DATA static u8 *sTrainerBIntroSpeech = NULL; -EWRAM_DATA static u8 *sTrainerADefeatSpeech = NULL; -EWRAM_DATA static u8 *sTrainerBDefeatSpeech = NULL; -EWRAM_DATA static u8 *sTrainerVictorySpeech = NULL; -EWRAM_DATA static u8 *sTrainerCannotBattleSpeech = NULL; EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; -EWRAM_DATA static u8 *sTrainerABattleScriptRetAddr = NULL; -EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0; @@ -163,114 +136,6 @@ static const u8 sBattleTransitionTable_BattleDome[] = B_TRANSITION_FRONTIER_SQUARES_SPIRAL }; -static const struct TrainerBattleParameter sOrdinaryBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -static const struct TrainerBattleParameter sContinueScriptBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -static const struct TrainerBattleParameter sDoubleBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - -// two trainers, each with a defeat speech -static const struct TrainerBattleParameter sTrainerTwoTrainerBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_CLEAR_VAL_16BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerBIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, -}; - #define REMATCH(trainer1, trainer2, trainer3, trainer4, trainer5, map) \ { \ .trainerIds = {trainer1, trainer2, trainer3, trainer4, trainer5}, \ @@ -896,8 +761,8 @@ u8 GetTrainerBattleTransition(void) u8 transitionType; u8 enemyLevel; u8 playerLevel; - u32 trainerId = SanitizeTrainerId(gTrainerBattleOpponent_A); - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerId = SanitizeTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (DoesTrainerHaveMugshot(trainerId)) return B_TRANSITION_MUGSHOT; @@ -1033,30 +898,14 @@ static void TryUpdateGymLeaderRematchFromTrainer(void) UpdateGymLeaderRematch(); } -// why not just use the macros? maybe its because they didnt want to uncast const every time? -static u32 TrainerBattleLoadArg32(const u8 *ptr) -{ - return T1_READ_32(ptr); -} - -static u16 TrainerBattleLoadArg16(const u8 *ptr) -{ - return T1_READ_16(ptr); -} - -static u8 TrainerBattleLoadArg8(const u8 *ptr) -{ - return T1_READ_8(ptr); -} - static u16 GetTrainerAFlag(void) { - return TRAINER_FLAGS_START + gTrainerBattleOpponent_A; + return TRAINER_FLAGS_START + TRAINER_BATTLE_PARAM.battleOpponentA; } static u16 GetTrainerBFlag(void) { - return TRAINER_FLAGS_START + gTrainerBattleOpponent_B; + return TRAINER_FLAGS_START + TRAINER_BATTLE_PARAM.battleOpponentB; } static bool32 IsPlayerDefeated(u32 battleOutcome) @@ -1079,198 +928,227 @@ static bool32 IsPlayerDefeated(u32 battleOutcome) void ResetTrainerOpponentIds(void) { - gTrainerBattleOpponent_A = 0; - gTrainerBattleOpponent_B = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentB = 0; } -static void InitTrainerBattleVariables(void) +void SetMapVarsToTrainerA(void) { - sTrainerBattleMode = 0; - if (gApproachingTrainerId == 0) + if (TRAINER_BATTLE_PARAM.objEventLocalIdA != 0) { - sTrainerAIntroSpeech = NULL; - sTrainerADefeatSpeech = NULL; - sTrainerABattleScriptRetAddr = NULL; + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdA; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); } - else +} + +void SetMapVarsToTrainerB(void) +{ + if (TRAINER_BATTLE_PARAM.objEventLocalIdB != 0) { - sTrainerBIntroSpeech = NULL; - sTrainerBDefeatSpeech = NULL; - sTrainerBBattleScriptRetAddr = NULL; + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdB; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdB, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); } - sTrainerObjectEventLocalId = 0; - sTrainerVictorySpeech = NULL; - sTrainerCannotBattleSpeech = NULL; +} + +void InitTrainerBattleVariables(void) +{ sTrainerBattleEndScript = NULL; + memset(gTrainerBattleParameter.data, 0, sizeof(gTrainerBattleParameter)); } -static inline void SetU8(void *ptr, u8 value) +void TrainerBattleLoadArgsTrainerA(const u8* data) { - *(u8 *)(ptr) = value; + TrainerBattleParameter *temp = (TrainerBattleParameter*)data; + + TRAINER_BATTLE_PARAM.playMusicA = temp->params.playMusicA; + TRAINER_BATTLE_PARAM.objEventLocalIdA = temp->params.objEventLocalIdA; + TRAINER_BATTLE_PARAM.battleOpponentA = temp->params.battleOpponentA; + TRAINER_BATTLE_PARAM.introTextA = temp->params.introTextA; + TRAINER_BATTLE_PARAM.defeatTextA = temp->params.defeatTextA; + TRAINER_BATTLE_PARAM.battleScriptRetAddrA = temp->params.battleScriptRetAddrA; } -static inline void SetU16(void *ptr, u16 value) +void TrainerBattleLoadArgsTrainerB(const u8* data) { - *(u16 *)(ptr) = value; + TrainerBattleParameter *temp = (TrainerBattleParameter*)data; + + TRAINER_BATTLE_PARAM.playMusicB = temp->params.playMusicB; + TRAINER_BATTLE_PARAM.objEventLocalIdB = temp->params.objEventLocalIdB; + TRAINER_BATTLE_PARAM.battleOpponentB = temp->params.battleOpponentB; + TRAINER_BATTLE_PARAM.introTextB = temp->params.introTextB; + TRAINER_BATTLE_PARAM.defeatTextB = temp->params.defeatTextB; + TRAINER_BATTLE_PARAM.battleScriptRetAddrB = temp->params.battleScriptRetAddrB; } -static inline void SetU32(void *ptr, u32 value) +// loads trainer A parameter to trainer B. Used for second trainer in trainer_see.c +void TrainerBattleLoadArgsSecondTrainer(const u8* data) { - *(u32 *)(ptr) = value; + TrainerBattleParameter *temp = (TrainerBattleParameter*)data; + + TRAINER_BATTLE_PARAM.playMusicB = temp->params.playMusicA; + TRAINER_BATTLE_PARAM.objEventLocalIdB = temp->params.objEventLocalIdA; + TRAINER_BATTLE_PARAM.battleOpponentB = temp->params.battleOpponentA; + TRAINER_BATTLE_PARAM.introTextB = temp->params.introTextA; + TRAINER_BATTLE_PARAM.defeatTextB = temp->params.defeatTextA; + TRAINER_BATTLE_PARAM.battleScriptRetAddrB = temp->params.battleScriptRetAddrA; } -static inline void SetPtr(const void *ptr, const void *value) +void TrainerBattleLoadArgs(const u8* data) { - *(const void **)(ptr) = value; + InitTrainerBattleVariables(); + memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameter)); + sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameter); + DebugPrintTrainerParams((&gTrainerBattleParameter)); } -static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, const u8 *data) +void MultiTrainerBattleLoadArgs(const u8* data) { - while (1) - { - switch (specs->ptrType) - { - case TRAINER_PARAM_LOAD_VAL_8BIT: - SetU8(specs->varPtr, TrainerBattleLoadArg8(data)); - data += 1; - break; - case TRAINER_PARAM_LOAD_VAL_16BIT: - SetU16(specs->varPtr, TrainerBattleLoadArg16(data)); - data += 2; - break; - case TRAINER_PARAM_LOAD_VAL_32BIT: - SetU32(specs->varPtr, TrainerBattleLoadArg32(data)); - data += 4; - break; - case TRAINER_PARAM_CLEAR_VAL_8BIT: - SetU8(specs->varPtr, 0); - break; - case TRAINER_PARAM_CLEAR_VAL_16BIT: - SetU16(specs->varPtr, 0); - break; - case TRAINER_PARAM_CLEAR_VAL_32BIT: - SetU32(specs->varPtr, 0); - break; - case TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR: - SetPtr(specs->varPtr, data); - return; - } - specs++; - } + MultiTrainerBattleParameter* temp = (MultiTrainerBattleParameter*)data; + + InitTrainerBattleVariables(); + + TRAINER_BATTLE_PARAM.battleOpponentA = temp->params.battleOpponentA; + TRAINER_BATTLE_PARAM.defeatTextA = temp->params.defeatTextA; + + TRAINER_BATTLE_PARAM.battleOpponentB = temp->params.battleOpponentB; + TRAINER_BATTLE_PARAM.defeatTextB = temp->params.defeatTextB; } -void SetMapVarsToTrainer(void) +const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 type, const u8* scriptEndPtr) { - if (sTrainerObjectEventLocalId != 0) + sTrainerBattleEndScript = (u8*)scriptEndPtr; + switch (type) { - gSpecialVar_LastTalked = sTrainerObjectEventLocalId; - gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(sTrainerObjectEventLocalId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + case TRAINER_BATTLE_HILL: + if (gApproachingTrainerId == 0) + { + SetMapVarsToTrainerA(); + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked); + } + else + { + SetMapVarsToTrainerB(); + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked); + } + return EventScript_TryDoNormalTrainerBattle; + case TRAINER_BATTLE_PYRAMID: + if (gApproachingTrainerId == 0) + { + SetMapVarsToTrainerA(); + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); + } + else + { + SetMapVarsToTrainerB(); + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); + } + return EventScript_TryDoNormalTrainerBattle; + default: + return NULL; } } -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) +#define PUSH(script) PtrStackPushU8(scrStack, script); + +const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - if (TrainerBattleLoadArg8(data) != TRAINER_BATTLE_SET_TRAINER_B) - InitTrainerBattleVariables(); - sTrainerBattleMode = TrainerBattleLoadArg8(data); + if (TRAINER_BATTLE_PARAM.playMusicA) + { + PUSH(EventSnippet_PlayTrainerEncounterMusic); + } + + PUSH(EventSnippet_TrainerApproach); - switch (sTrainerBattleMode) + if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - case TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT: - TrainerBattleLoadArgs(sOrdinaryNoIntroBattleParams, data); - return EventScript_DoNoIntroTrainerBattle; - case TRAINER_BATTLE_DOUBLE: - TrainerBattleLoadArgs(sDoubleBattleParams, data); - SetMapVarsToTrainer(); - return EventScript_TryDoDoubleTrainerBattle; - case TRAINER_BATTLE_CONTINUE_SCRIPT: - if (gApproachingTrainerId == 0) - { - TrainerBattleLoadArgs(sContinueScriptBattleParams, data); - SetMapVarsToTrainer(); - } - else - { - TrainerBattleLoadArgs(sTrainerBContinueScriptBattleParams, data); - } - return EventScript_TryDoNormalTrainerBattle; - case TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC: - TrainerBattleLoadArgs(sContinueScriptBattleParams, data); - SetMapVarsToTrainer(); - return EventScript_TryDoNormalTrainerBattle; - case TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE: - case TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC: - TrainerBattleLoadArgs(sContinueScriptDoubleBattleParams, data); - SetMapVarsToTrainer(); - return EventScript_TryDoDoubleTrainerBattle; -#if FREE_MATCH_CALL == FALSE - case TRAINER_BATTLE_REMATCH_DOUBLE: - TrainerBattleLoadArgs(sDoubleBattleParams, data); - SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A); - return EventScript_TryDoDoubleRematchBattle; - case TRAINER_BATTLE_REMATCH: - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A); - return EventScript_TryDoRematchBattle; -#endif //FREE_MATCH_CALL - case TRAINER_BATTLE_PYRAMID: - if (gApproachingTrainerId == 0) - { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); - } - else - { - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - gTrainerBattleOpponent_B = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); - } - return EventScript_TryDoNormalTrainerBattle; - case TRAINER_BATTLE_SET_TRAINER_A: - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - return sTrainerBattleEndScript; - case TRAINER_BATTLE_SET_TRAINER_B: - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - return sTrainerBattleEndScript; - case TRAINER_BATTLE_HILL: - if (gApproachingTrainerId == 0) - { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = LocalIdToHillTrainerId(gSpecialVar_LastTalked); - } - else - { - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - gTrainerBattleOpponent_B = LocalIdToHillTrainerId(gSpecialVar_LastTalked); - } - return EventScript_TryDoNormalTrainerBattle; - case TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO: - gNoOfApproachingTrainers = 2; // set TWO_OPPONENTS gBattleTypeFlags - gApproachingTrainerId = 1; // prevent trainer approach - TrainerBattleLoadArgs(sTrainerTwoTrainerBattleParams, data); - return EventScript_DoNoIntroTrainerBattle; - default: - if (gApproachingTrainerId == 0) + PUSH(EventSnippet_ShowTrainerIntroMsg); + } + + if (TryPrepareSecondApproachingTrainer2()) { + SetMapVarsToTrainerB(); + + PUSH(EventSnippet_PrepareSecondTrainerApproach); + if (TRAINER_BATTLE_PARAM.playMusicB) { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - SetMapVarsToTrainer(); + PUSH(EventSnippet_PlayTrainerEncounterMusic); } - else + + PUSH(EventSnippet_TrainerApproach); + + if (TRAINER_BATTLE_PARAM.introTextB) { - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); + PUSH(EventSnippet_ShowTrainerIntroMsg); } - return EventScript_TryDoNormalTrainerBattle; } + + PUSH(EventSnippet_DoTrainerBattle); + PUSH(EventSnippet_EndTrainerBattle); + return NULL; +} + +const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching) +{ + DebugPrintTrainerParams((&gTrainerBattleParameter)); + + if (isApproaching) + { + return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); + } + + SetMapVarsToTrainerA(); + PUSH(EventSnippet_Lock); + PUSH(EventSnippet_RevealTrainer); + + if ((GetTrainerFlag() && !TRAINER_BATTLE_PARAM.isRematch) + || (!IsTrainerReadyForRematch() && TRAINER_BATTLE_PARAM.isRematch)) { + PUSH(EventSnippet_GotoPostBattleScript); + return NULL; + } + + if (TRAINER_BATTLE_PARAM.isDoubleBattle && !HasEnoughMonsForDoubleBattle2()) + { + PUSH(EventScript_NotEnoughMonsForDoubleBattle); + return NULL; + } + + if (TRAINER_BATTLE_PARAM.isRematch) + { + TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); + } + + if (TRAINER_BATTLE_PARAM.playMusicA) + { + PUSH(EventSnippet_PlayTrainerEncounterMusic); + } + + PUSH(EventSnippet_SetTrainerFacingDirection); + + if (TRAINER_BATTLE_PARAM.introTextA != NULL) + { + PUSH(EventSnippet_ShowTrainerIntroMsg); + } + + if (TRAINER_BATTLE_PARAM.isRematch) + { + PUSH(EventSnippet_DoRematchTrainerBattle); + } + else + { + PUSH(EventSnippet_DoTrainerBattle); + } + + PUSH(EventSnippet_EndTrainerBattle); + + + DebugPrintStack(scrStack); + return NULL; } void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript) { gSelectedObjectEvent = trainerObjEventId; gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId; - BattleSetup_ConfigureTrainerBattle(trainerScript + 1); + BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL, TRUE); ScriptContext_SetupScript(EventScript_StartTrainerApproach); LockPlayerFieldControls(); } @@ -1279,7 +1157,7 @@ void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript) { gSelectedObjectEvent = trainerObjEventId; gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId; - BattleSetup_ConfigureTrainerBattle(trainerScript + 1); + BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL, TRUE); } void SetUpTwoTrainersBattle(void) @@ -1288,12 +1166,17 @@ void SetUpTwoTrainersBattle(void) LockPlayerFieldControls(); } +// the opcode is 1 byte in size. since data points at the opcode we move one byte further +#define OPCODE_OFFSET 1 + bool32 GetTrainerFlagFromScriptPointer(const u8 *data) { - u32 flag = TrainerBattleLoadArg16(data + 2); - return FlagGet(TRAINER_FLAGS_START + flag); + TrainerBattleParameter *temp = (TrainerBattleParameter*)(data + OPCODE_OFFSET); + return FlagGet(TRAINER_FLAGS_START + temp->params.battleOpponentA); } +#undef OPCODE_OFFSET + // Set trainer's movement type so they stop and remain facing that direction // Note: Only for trainers who are spoken to directly // For trainers who spot the player this is handled by PlayerFaceApproachingTrainer @@ -1303,11 +1186,6 @@ void SetTrainerFacingDirection(void) SetTrainerMovementType(objectEvent, GetTrainerFacingDirectionMovementType(objectEvent->facingDirection)); } -u8 GetTrainerBattleMode(void) -{ - return sTrainerBattleMode; -} - bool8 GetTrainerFlag(void) { if (InBattlePyramid()) @@ -1320,7 +1198,7 @@ bool8 GetTrainerFlag(void) static void SetBattledTrainersFlags(void) { - if (gTrainerBattleOpponent_B != 0) + if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) FlagSet(GetTrainerBFlag()); FlagSet(GetTrainerAFlag()); } @@ -1347,11 +1225,14 @@ void ClearTrainerFlag(u16 trainerId) void BattleSetup_StartTrainerBattle(void) { - if (gNoOfApproachingTrainers == 2) - gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER); - else - gBattleTypeFlags = (BATTLE_TYPE_TRAINER); + gBattleTypeFlags = (BATTLE_TYPE_TRAINER); + if ((TRAINER_BATTLE_PARAM.battleOpponentA != TRAINER_NONE && TRAINER_BATTLE_PARAM.battleOpponentB != TRAINER_NONE) + || gNoOfApproachingTrainers == 2) + { + gBattleTypeFlags |= (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS); + } + if (InBattlePyramid()) { VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0); @@ -1440,7 +1321,7 @@ static void CB2_EndTrainerBattle(void) { HandleBattleVariantEndParty(); - if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) { DowngradeBadPoison(); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); @@ -1466,7 +1347,7 @@ static void CB2_EndTrainerBattle(void) static void CB2_EndRematchBattle(void) { - if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) { DowngradeBadPoison(); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); @@ -1521,32 +1402,37 @@ void ShowTrainerIntroSpeech(void) const u8 *BattleSetup_GetScriptAddrAfterBattle(void) { - if (sTrainerBattleEndScript != NULL) - return sTrainerBattleEndScript; + if (sTrainerBattleEndScript != NULL) { + return sTrainerBattleEndScript; + } else return EventScript_TestSignpostMsg; } +void BattleSetup_SetScriptAddrAfterBattle(const u8* ptr) +{ + sTrainerBattleEndScript = (u8*)ptr; +} + const u8 *BattleSetup_GetTrainerPostBattleScript(void) { if (sShouldCheckTrainerBScript) { sShouldCheckTrainerBScript = FALSE; - if (sTrainerBBattleScriptRetAddr != NULL) + if (TRAINER_BATTLE_PARAM.battleScriptRetAddrB != NULL) { gWhichTrainerToFaceAfterBattle = 1; - return sTrainerBBattleScriptRetAddr; + return TRAINER_BATTLE_PARAM.battleScriptRetAddrB; } } else { - if (sTrainerABattleScriptRetAddr != NULL) + if (TRAINER_BATTLE_PARAM.battleScriptRetAddrA != NULL) { gWhichTrainerToFaceAfterBattle = 0; - return sTrainerABattleScriptRetAddr; + return TRAINER_BATTLE_PARAM.battleScriptRetAddrA; } } - return EventScript_TryGetTrainerScript; } @@ -1561,59 +1447,56 @@ void PlayTrainerEncounterMusic(void) u16 music; if (gApproachingTrainerId == 0) - trainerId = gTrainerBattleOpponent_A; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; else - trainerId = gTrainerBattleOpponent_B; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentB; - if (sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC - && sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC) + switch (GetTrainerEncounterMusicId(trainerId)) { - switch (GetTrainerEncounterMusicId(trainerId)) - { - case TRAINER_ENCOUNTER_MUSIC_MALE: - music = MUS_ENCOUNTER_MALE; - break; - case TRAINER_ENCOUNTER_MUSIC_FEMALE: - music = MUS_ENCOUNTER_FEMALE; - break; - case TRAINER_ENCOUNTER_MUSIC_GIRL: - music = MUS_ENCOUNTER_GIRL; - break; - case TRAINER_ENCOUNTER_MUSIC_INTENSE: - music = MUS_ENCOUNTER_INTENSE; - break; - case TRAINER_ENCOUNTER_MUSIC_COOL: - music = MUS_ENCOUNTER_COOL; - break; - case TRAINER_ENCOUNTER_MUSIC_AQUA: - music = MUS_ENCOUNTER_AQUA; - break; - case TRAINER_ENCOUNTER_MUSIC_MAGMA: - music = MUS_ENCOUNTER_MAGMA; - break; - case TRAINER_ENCOUNTER_MUSIC_SWIMMER: - music = MUS_ENCOUNTER_SWIMMER; - break; - case TRAINER_ENCOUNTER_MUSIC_TWINS: - music = MUS_ENCOUNTER_TWINS; - break; - case TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR: - music = MUS_ENCOUNTER_ELITE_FOUR; - break; - case TRAINER_ENCOUNTER_MUSIC_HIKER: - music = MUS_ENCOUNTER_HIKER; - break; - case TRAINER_ENCOUNTER_MUSIC_INTERVIEWER: - music = MUS_ENCOUNTER_INTERVIEWER; - break; - case TRAINER_ENCOUNTER_MUSIC_RICH: - music = MUS_ENCOUNTER_RICH; - break; - default: - music = MUS_ENCOUNTER_SUSPICIOUS; - } - PlayNewMapMusic(music); + case TRAINER_ENCOUNTER_MUSIC_MALE: + music = MUS_ENCOUNTER_MALE; + break; + case TRAINER_ENCOUNTER_MUSIC_FEMALE: + music = MUS_ENCOUNTER_FEMALE; + break; + case TRAINER_ENCOUNTER_MUSIC_GIRL: + music = MUS_ENCOUNTER_GIRL; + break; + case TRAINER_ENCOUNTER_MUSIC_INTENSE: + music = MUS_ENCOUNTER_INTENSE; + break; + case TRAINER_ENCOUNTER_MUSIC_COOL: + music = MUS_ENCOUNTER_COOL; + break; + case TRAINER_ENCOUNTER_MUSIC_AQUA: + music = MUS_ENCOUNTER_AQUA; + break; + case TRAINER_ENCOUNTER_MUSIC_MAGMA: + music = MUS_ENCOUNTER_MAGMA; + break; + case TRAINER_ENCOUNTER_MUSIC_SWIMMER: + music = MUS_ENCOUNTER_SWIMMER; + break; + case TRAINER_ENCOUNTER_MUSIC_TWINS: + music = MUS_ENCOUNTER_TWINS; + break; + case TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR: + music = MUS_ENCOUNTER_ELITE_FOUR; + break; + case TRAINER_ENCOUNTER_MUSIC_HIKER: + music = MUS_ENCOUNTER_HIKER; + break; + case TRAINER_ENCOUNTER_MUSIC_INTERVIEWER: + music = MUS_ENCOUNTER_INTERVIEWER; + break; + case TRAINER_ENCOUNTER_MUSIC_RICH: + music = MUS_ENCOUNTER_RICH; + break; + default: + music = MUS_ENCOUNTER_SUSPICIOUS; } + PlayNewMapMusic(music); + } static const u8 *ReturnEmptyStringIfNull(const u8 *string) @@ -1627,19 +1510,19 @@ static const u8 *ReturnEmptyStringIfNull(const u8 *string) static const u8 *GetIntroSpeechOfApproachingTrainer(void) { if (gApproachingTrainerId == 0) - return ReturnEmptyStringIfNull(sTrainerAIntroSpeech); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.introTextA); else - return ReturnEmptyStringIfNull(sTrainerBIntroSpeech); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.introTextB); } const u8 *GetTrainerALoseText(void) { const u8 *string; - if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) string = GetSecretBaseTrainerLoseText(); else - string = sTrainerADefeatSpeech; + string = TRAINER_BATTLE_PARAM.defeatTextA; StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(string)); return gStringVar4; @@ -1647,18 +1530,18 @@ const u8 *GetTrainerALoseText(void) const u8 *GetTrainerBLoseText(void) { - StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(sTrainerBDefeatSpeech)); + StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.defeatTextB)); return gStringVar4; } const u8 *GetTrainerWonSpeech(void) { - return ReturnEmptyStringIfNull(sTrainerVictorySpeech); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.victoryText); } static const u8 *GetTrainerCantBattleSpeech(void) { - return ReturnEmptyStringIfNull(sTrainerCannotBattleSpeech); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.cannotBattleText); } s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId) @@ -1897,7 +1780,7 @@ static void RegisterTrainerInMatchCall(void) { if (FlagGet(FLAG_HAS_MATCH_CALL)) { - u32 matchCallFlagId = GetTrainerMatchCallFlag(gTrainerBattleOpponent_A); + u32 matchCallFlagId = GetTrainerMatchCallFlag(TRAINER_BATTLE_PARAM.battleOpponentA); if (matchCallFlagId != 0xFFFF) FlagSet(matchCallFlagId); } @@ -1994,15 +1877,15 @@ u16 GetLastBeatenRematchTrainerId(u16 trainerId) bool8 ShouldTryRematchBattle(void) { - if (IsFirstTrainerIdReadyForRematch(gRematchTable, gTrainerBattleOpponent_A)) + if (IsFirstTrainerIdReadyForRematch(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA)) return TRUE; - return WasSecondRematchWon(gRematchTable, gTrainerBattleOpponent_A); + return WasSecondRematchWon(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); } bool8 IsTrainerReadyForRematch(void) { - return IsTrainerReadyForRematch_(gRematchTable, gTrainerBattleOpponent_A); + return IsTrainerReadyForRematch_(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); } static void HandleRematchVarsOnBattleEnd(void) @@ -2010,7 +1893,7 @@ static void HandleRematchVarsOnBattleEnd(void) if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) && (I_VS_SEEKER_CHARGING != 0)) ClearRematchMovementByTrainerId(); - ClearTrainerWantRematchState(gRematchTable, gTrainerBattleOpponent_A); + ClearTrainerWantRematchState(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); SetBattledTrainersFlags(); } diff --git a/src/battle_tent.c b/src/battle_tent.c index 49df90ffd61e..0d7cb61bde4b 100644 --- a/src/battle_tent.c +++ b/src/battle_tent.c @@ -127,14 +127,14 @@ static void SetVerdanturfTentPrize(void) static void SetVerdanturfTentTrainerGfx(void) { - gTrainerBattleOpponent_A = (u32)((Random() % 255) * 5) / 64; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = (u32)((Random() % 255) * 5) / 64; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void BufferVerdanturfTentTrainerIntro(void) { - if (gTrainerBattleOpponent_A < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].speechBefore); } static void SaveVerdanturfTentChallenge(void) @@ -218,7 +218,7 @@ static void GiveFallarborTentPrize(void) static void BufferFallarborTentTrainerName(void) { - GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar1, TRAINER_BATTLE_PARAM.battleOpponentA); } void CallSlateportTentFunction(void) @@ -375,8 +375,8 @@ static void GenerateOpponentMons(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_A = trainerId; - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; + monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].monSet; while (monSet[numMons] != 0xFFFF) numMons++; if (numMons > 8) @@ -385,9 +385,9 @@ static void GenerateOpponentMons(void) } if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < TENT_STAGES_PER_CHALLENGE - 1) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].monSet; i = 0; while (i != FRONTIER_PARTY_SIZE) { diff --git a/src/battle_tower.c b/src/battle_tower.c index 18b3d338863b..bc5815b5035f 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -823,7 +823,7 @@ static void InitTowerChallenge(void) ValidateBattleTowerRecordChecksums(); SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetTowerData(void) @@ -874,7 +874,7 @@ static void SetTowerData(void) static void SetTowerBattleWon(void) { #if FREE_BATTLE_TOWER_E_READER == FALSE - if (gTrainerBattleOpponent_A == TRAINER_EREADER) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_EREADER) ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer); #endif //FREE_BATTLE_TOWER_E_READER @@ -946,7 +946,7 @@ static bool8 ChooseSpecialBattleTowerTrainer(void) if (idsCount != 0) { - gTrainerBattleOpponent_A = trainerIds[Random() % idsCount]; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerIds[Random() % idsCount]; return TRUE; } else @@ -973,15 +973,15 @@ static void SetNextFacilityOpponent(void) if (battleMode == FRONTIER_MODE_MULTIS || battleMode == FRONTIER_MODE_LINK_MULTIS) { id = gSaveBlock2Ptr->frontier.curChallengeBattleNum; - gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.trainerIds[id * 2]; - gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.trainerIds[id * 2 + 1]; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1); + TRAINER_BATTLE_PARAM.battleOpponentA = gSaveBlock2Ptr->frontier.trainerIds[id * 2]; + TRAINER_BATTLE_PARAM.battleOpponentB = gSaveBlock2Ptr->frontier.trainerIds[id * 2 + 1]; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentB, 1); } else if (ChooseSpecialBattleTowerTrainer()) { - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; } else { @@ -1000,10 +1000,10 @@ static void SetNextFacilityOpponent(void) break; } - gTrainerBattleOpponent_A = id; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = id; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < FRONTIER_STAGES_PER_CHALLENGE) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; } } } @@ -1549,20 +1549,20 @@ static bool8 IsFrontierTrainerFemale(u16 trainerId) void FillFrontierTrainerParty(u8 monsCount) { ZeroEnemyPartyMons(); - FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount); + FillTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0, monsCount); } void FillFrontierTrainersParties(u8 monsCount) { ZeroEnemyPartyMons(); - FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount); - FillTrainerParty(gTrainerBattleOpponent_B, 3, monsCount); + FillTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0, monsCount); + FillTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentB, 3, monsCount); } static void FillTentTrainerParty(u8 monsCount) { ZeroEnemyPartyMons(); - FillTentTrainerParty_(gTrainerBattleOpponent_A, 0, monsCount); + FillTentTrainerParty_(TRAINER_BATTLE_PARAM.battleOpponentA, 0, monsCount); } void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst) @@ -1667,7 +1667,7 @@ static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount) { // Normal battle frontier trainer. fixedIV = GetFrontierTrainerFixedIvs(trainerId); - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].monSet; } else if (trainerId == TRAINER_EREADER) { @@ -1789,9 +1789,9 @@ static void FillFactoryTrainerParty(void) { ZeroEnemyPartyMons(); if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT) - FillFactoryFrontierTrainerParty(gTrainerBattleOpponent_A, 0); + FillFactoryFrontierTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); else - FillFactoryTentTrainerParty(gTrainerBattleOpponent_A, 0); + FillFactoryTentTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId) @@ -1886,9 +1886,9 @@ static void GetOpponentIntroSpeech(void) SetFacilityPtrsGetLevel(); if (gSpecialVar_0x8005) - trainerId = gTrainerBattleOpponent_B; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentB; else - trainerId = gTrainerBattleOpponent_A; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; #if FREE_BATTLE_TOWER_E_READER == FALSE if (trainerId == TRAINER_EREADER) @@ -2011,7 +2011,7 @@ void DoSpecialTrainerBattle(void) for (i = 0; i < (int)ARRAY_COUNT(gSaveBlock2Ptr->frontier.ereaderTrainer.party); i++) CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i]); gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_EREADER_TRAINER; - gTrainerBattleOpponent_A = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_E_READER)); @@ -2021,7 +2021,7 @@ void DoSpecialTrainerBattle(void) gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOME; if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES) gBattleTypeFlags |= BATTLE_TYPE_DOUBLE; - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE); CreateTask(Task_StartBattleAfterTransition, 1); CreateTask_PlayMapChosenOrBattleBGM(0); @@ -2086,7 +2086,7 @@ void DoSpecialTrainerBattle(void) } else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer { - gTrainerBattleOpponent_B = 0xFFFF; + TRAINER_BATTLE_PARAM.battleOpponentB = 0xFFFF; gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; } else // MULTI_BATTLE_2_VS_2 @@ -2607,10 +2607,10 @@ static void LoadLinkMultiOpponentsData(void) { ResetBlockReceivedFlags(); memcpy(&gSaveBlock2Ptr->frontier.trainerIds, gBlockRecvBuffer, sizeof(gSaveBlock2Ptr->frontier.trainerIds)); - gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2]; - gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2 + 1]; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1); + TRAINER_BATTLE_PARAM.battleOpponentA = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2]; + TRAINER_BATTLE_PARAM.battleOpponentB = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2 + 1]; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentB, 1); if (gReceivedRemoteLinkPlayers && gWirelessCommType == 0) gSpecialVar_Result = 4; else @@ -2652,10 +2652,10 @@ static void SetTowerInterviewData(void) if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_SINGLES) return; - GetFrontierTrainerName(text, gTrainerBattleOpponent_A); + GetFrontierTrainerName(text, TRAINER_BATTLE_PARAM.battleOpponentA); StripExtCtrlCodes(text); StringCopy(gSaveBlock2Ptr->frontier.towerInterview.opponentName, text); - GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.towerInterview.opponentLanguage, gTrainerBattleOpponent_A); + GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.towerInterview.opponentLanguage, TRAINER_BATTLE_PARAM.battleOpponentA); gSaveBlock2Ptr->frontier.towerInterview.opponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[1]], MON_DATA_SPECIES, NULL); gSaveBlock2Ptr->frontier.towerInterview.playerSpecies = GetMonData(&gPlayerParty[gBattlerPartyIndexes[0]], MON_DATA_SPECIES, NULL); for (i = 0; i < VANILLA_POKEMON_NAME_LENGTH + 1; i++) @@ -3418,10 +3418,10 @@ static void SetNextBattleTentOpponent(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_A = trainerId; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < TENT_STAGES_PER_CHALLENGE) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; } static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) @@ -3435,7 +3435,7 @@ static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) u32 otID = 0; u16 monId; - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].monSet; bfMonCount = 0; monId = monSet[bfMonCount]; diff --git a/src/battle_transition.c b/src/battle_transition.c index fbaa5cc0de34..e685b49e0c08 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -2260,7 +2260,7 @@ static bool8 Mugshot_SetGfx(struct Task *task) s16 i, j; u16 *tilemap, *tileset; const u16 *mugshotsMap = sMugshotsTilemap; - u8 mugshotColor = GetTrainerMugshotColorFromId(gTrainerBattleOpponent_A); + u8 mugshotColor = GetTrainerMugshotColorFromId(TRAINER_BATTLE_PARAM.battleOpponentA); GetBg0TilesDst(&tilemap, &tileset); CpuSet(sEliteFour_Tileset, tileset, 0xF0); @@ -2519,7 +2519,7 @@ static void Mugshots_CreateTrainerPics(struct Task *task) { struct Sprite *opponentSprite, *playerSprite; - u8 trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + u8 trainerPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.battleOpponentA); s16 opponentRotationScales = 0; gReservedSpritePaletteCount = 10; diff --git a/src/battle_util.c b/src/battle_util.c index 19551f885410..abf7b00a7a3b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11344,7 +11344,7 @@ bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler) return FALSE; else if (GetBattlerSide(battler) != B_SIDE_PLAYER) return FALSE; - else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) return FALSE; else if (FlagGet(badgeFlag)) return TRUE; diff --git a/src/cable_club.c b/src/cable_club.c index d6a2903fd47a..bc4e91a62d64 100644 --- a/src/cable_club.c +++ b/src/cable_club.c @@ -867,7 +867,7 @@ static void Task_StartWiredCableClubBattle(u8 taskId) SetLinkBattleTypeFlags(gSpecialVar_0x8004); CleanupOverworldWindowsAndTilemaps(); - gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_LINK_OPPONENT; SetMainCallback2(CB2_InitBattle); gMain.savedCallback = CB2_ReturnFromCableClubBattle; DestroyTask(taskId); @@ -933,7 +933,7 @@ static void Task_StartWirelessCableClubBattle(u8 taskId) gLinkPlayers[0].linkType = LINKTYPE_BATTLE; SetLinkBattleTypeFlags(gSpecialVar_0x8004); CleanupOverworldWindowsAndTilemaps(); - gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_LINK_OPPONENT; SetMainCallback2(CB2_InitBattle); gMain.savedCallback = CB2_ReturnFromCableClubBattle; DestroyTask(taskId); diff --git a/src/frontier_util.c b/src/frontier_util.c index 30c22d4442bc..2f78db23106e 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -1849,7 +1849,7 @@ void ResetFrontierTrainerIds(void) static void IsTrainerFrontierBrain(void) { - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) gSpecialVar_Result = TRUE; else gSpecialVar_Result = FALSE; @@ -1900,7 +1900,7 @@ static void GiveBattlePoints(void) challengeNum = ARRAY_COUNT(sBattlePointAwards[0][0]) - 1; points = sBattlePointAwards[facility][battleMode][challengeNum]; - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) points += 10; gSaveBlock2Ptr->frontier.battlePoints += points; ConvertIntToDecimalStringN(gStringVar1, points, STR_CONV_MODE_LEFT_ALIGN, 2); @@ -1910,7 +1910,7 @@ static void GiveBattlePoints(void) points = gSaveBlock2Ptr->frontier.cardBattlePoints; points += sBattlePointAwards[facility][battleMode][challengeNum]; IncrementDailyBattlePoints(sBattlePointAwards[facility][battleMode][challengeNum]); - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) { points += 10; IncrementDailyBattlePoints(10); @@ -2182,10 +2182,10 @@ static void BufferFrontierTrainerName(void) switch (gSpecialVar_0x8005) { case 0: - GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar1, TRAINER_BATTLE_PARAM.battleOpponentA); break; case 1: - GetFrontierTrainerName(gStringVar2, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar2, TRAINER_BATTLE_PARAM.battleOpponentA); break; } } @@ -2564,7 +2564,7 @@ u16 GetFrontierBrainMonSpecies(u8 monId) void SetFrontierBrainObjEventGfx(u8 facility) { - gTrainerBattleOpponent_A = TRAINER_FRONTIER_BRAIN; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_FRONTIER_BRAIN; VarSet(VAR_OBJ_GFX_ID_0, gFrontierBrainInfo[facility].objEventGfx); } diff --git a/src/pokemon.c b/src/pokemon.c index bb590abd6301..54b9c890ba65 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5199,7 +5199,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) { u8 friendshipLevel = 0; s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); - u32 opponentTrainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 opponentTrainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (friendship > 99) friendshipLevel++; @@ -5766,11 +5766,11 @@ u16 GetBattleBGM(void) u8 trainerClass; if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) - trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A); + trainerClass = GetFrontierOpponentClass(TRAINER_BATTLE_PARAM.battleOpponentA); else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) trainerClass = TRAINER_CLASS_EXPERT; else - trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); switch (trainerClass) { @@ -5789,7 +5789,7 @@ u16 GetBattleBGM(void) case TRAINER_CLASS_RIVAL: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) return MUS_VS_RIVAL; - if (!StringCompare(GetTrainerNameFromId(gTrainerBattleOpponent_A), gText_BattleWallyName)) + if (!StringCompare(GetTrainerNameFromId(TRAINER_BATTLE_PARAM.battleOpponentA), gText_BattleWallyName)) return MUS_VS_TRAINER; return MUS_VS_RIVAL; case TRAINER_CLASS_ELITE_FOUR: diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 5e1ff63bbe1c..cfac41f7574e 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -349,8 +349,8 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->battleFlags = sBattleFlags; } - battleSave->opponentA = gTrainerBattleOpponent_A; - battleSave->opponentB = gTrainerBattleOpponent_B; + battleSave->opponentA = TRAINER_BATTLE_PARAM.battleOpponentA; + battleSave->opponentB = TRAINER_BATTLE_PARAM.battleOpponentB; battleSave->partnerId = gPartnerTrainerId; battleSave->multiplayerId = gRecordedBattleMultiplayerId; battleSave->lvlMode = gSaveBlock2Ptr->frontier.lvlMode; @@ -360,41 +360,41 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->textSpeed = gSaveBlock2Ptr->optionsTextSpeed; battleSave->AI_scripts = sAI_Scripts; - if (gTrainerBattleOpponent_A >= TRAINER_RECORD_MIXING_FRIEND && gTrainerBattleOpponent_A < TRAINER_RECORD_MIXING_APPRENTICE) + if (TRAINER_BATTLE_PARAM.battleOpponentA >= TRAINER_RECORD_MIXING_FRIEND && TRAINER_BATTLE_PARAM.battleOpponentA < TRAINER_RECORD_MIXING_APPRENTICE) { for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++) - battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].name[i]; - battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].facilityClass; + battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].name[i]; + battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].facilityClass; if (sBattleOutcome == B_OUTCOME_WON) { for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) - battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].speechLost[i]; + battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].speechLost[i]; } else { for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) - battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].speechWon[i]; + battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].speechWon[i]; } - battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].language; + battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].language; } - else if (gTrainerBattleOpponent_B >= TRAINER_RECORD_MIXING_FRIEND && gTrainerBattleOpponent_B < TRAINER_RECORD_MIXING_APPRENTICE) + else if (TRAINER_BATTLE_PARAM.battleOpponentB >= TRAINER_RECORD_MIXING_FRIEND && TRAINER_BATTLE_PARAM.battleOpponentB < TRAINER_RECORD_MIXING_APPRENTICE) { for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++) - battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].name[i]; - battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].facilityClass; + battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].name[i]; + battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].facilityClass; if (sBattleOutcome == B_OUTCOME_WON) { for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) - battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].speechLost[i]; + battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].speechLost[i]; } else { for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) - battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].speechWon[i]; + battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].speechWon[i]; } - battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].language; + battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].language; } else if (gPartnerTrainerId >= TRAINER_RECORD_MIXING_FRIEND && gPartnerTrainerId < TRAINER_RECORD_MIXING_APPRENTICE) { @@ -405,19 +405,19 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gPartnerTrainerId - TRAINER_RECORD_MIXING_FRIEND].language; } - if (gTrainerBattleOpponent_A >= TRAINER_RECORD_MIXING_APPRENTICE) + if (TRAINER_BATTLE_PARAM.battleOpponentA >= TRAINER_RECORD_MIXING_APPRENTICE) { - battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].id; + battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_APPRENTICE].id; for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) - battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; - battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].language; + battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->apprentices[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; + battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_APPRENTICE].language; } - else if (gTrainerBattleOpponent_B >= TRAINER_RECORD_MIXING_APPRENTICE) + else if (TRAINER_BATTLE_PARAM.battleOpponentB >= TRAINER_RECORD_MIXING_APPRENTICE) { - battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].id; + battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_APPRENTICE].id; for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++) - battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; - battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].language; + battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->apprentices[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; + battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[TRAINER_BATTLE_PARAM.battleOpponentB - TRAINER_RECORD_MIXING_APPRENTICE].language; } else if (gPartnerTrainerId >= TRAINER_RECORD_MIXING_APPRENTICE) { @@ -472,8 +472,8 @@ static void CB2_RecordedBattleEnd(void) gSaveBlock2Ptr->frontier.lvlMode = sLvlMode; gBattleOutcome = 0; gBattleTypeFlags = 0; - gTrainerBattleOpponent_A = 0; - gTrainerBattleOpponent_B = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentB = 0; gPartnerTrainerId = 0; RecordedBattle_RestoreSavedParties(); @@ -530,8 +530,8 @@ void SetVariablesForRecordedBattle(struct RecordedBattleSave *src) gRecordedBattleRngSeed = src->rngSeed; gBattleTypeFlags = src->battleFlags | BATTLE_TYPE_RECORDED; - gTrainerBattleOpponent_A = src->opponentA; - gTrainerBattleOpponent_B = src->opponentB; + TRAINER_BATTLE_PARAM.battleOpponentA = src->opponentA; + TRAINER_BATTLE_PARAM.battleOpponentB = src->opponentB; gPartnerTrainerId = src->partnerId; gRecordedBattleMultiplayerId = src->multiplayerId; sLvlMode = gSaveBlock2Ptr->frontier.lvlMode; diff --git a/src/scrcmd.c b/src/scrcmd.c index 2471f3b5959c..43b32ffca451 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1967,7 +1967,39 @@ bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx) bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) { - ctx->scriptPtr = BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr); + PtrStack trainerBattleScriptStack; + PtrStackInit(&trainerBattleScriptStack); + + TrainerBattleLoadArgs(ctx->scriptPtr); + BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr, &trainerBattleScriptStack, FALSE); + + const u8* ptr; + while ((ptr = PtrStackPopU8(&trainerBattleScriptStack)) != NULL) + { + ScriptPush(ctx, ptr); + } + + DebugPrintScriptStack; + + ctx->scriptPtr = ScriptPop(ctx); + + //DebugPrintScriptStack; + return FALSE; +} + +bool8 ScrCmd_facilitytrainerbattle(struct ScriptContext *ctx) +{ + u8 type = ScriptReadByte(ctx); + + InitTrainerBattleVariables(); + ctx->scriptPtr = BattleSetup_ConfigureFacilityTrainerBattle(type, ctx->scriptPtr); + return FALSE; +} + +bool8 ScrCmd_setmultitrainerbattle(struct ScriptContext *ctx) +{ + MultiTrainerBattleLoadArgs(ctx->scriptPtr); + return FALSE; } diff --git a/src/script.c b/src/script.c index e6e2aa264d86..bc19b726f3c1 100644 --- a/src/script.c +++ b/src/script.c @@ -127,7 +127,7 @@ bool8 RunScriptCommand(struct ScriptContext *ctx) return TRUE; } -static bool8 ScriptPush(struct ScriptContext *ctx, const u8 *ptr) +bool8 ScriptPush(struct ScriptContext *ctx, const u8 *ptr) { if (ctx->stackDepth + 1 >= (int)ARRAY_COUNT(ctx->stack)) { @@ -141,7 +141,7 @@ static bool8 ScriptPush(struct ScriptContext *ctx, const u8 *ptr) } } -static const u8 *ScriptPop(struct ScriptContext *ctx) +const u8 *ScriptPop(struct ScriptContext *ctx) { if (ctx->stackDepth == 0) return NULL; @@ -166,6 +166,7 @@ void ScriptReturn(struct ScriptContext *ctx) ctx->scriptPtr = ScriptPop(ctx); } + u16 ScriptReadHalfword(struct ScriptContext *ctx) { u16 value = *(ctx->scriptPtr++); @@ -271,6 +272,19 @@ void ScriptContext_Enable(void) LockPlayerFieldControls(); } +// Pops all scripts from one Stack and pushes them on the global script context +bool32 ScriptContext_PushFromStack(PtrStack *stack) +{ + const u8* ptr; + while ((ptr = (u8*)PtrStackPop(stack)) != NULL) + { + if (ScriptPush(&sGlobalScriptContext, ptr) == TRUE) + return FALSE; + } + DebugPrintGlobalScriptStack; + return TRUE; +} + // Sets up and runs a script in its own context immediately. The script will be // finished when this function returns. Used mainly by all of the map header // scripts (except the frame table scripts). diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index fc248435a90d..5fc3a4a10cb8 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -73,6 +73,12 @@ u8 ScriptGiveEgg(u16 species) return GiveMonToPlayer(&mon); } +// TODO verify that this is really always the same output as the script special variant +u8 HasEnoughMonsForDoubleBattle2(void) +{ + return GetMonsStateToDoubles() == PLAYER_HAS_TWO_USABLE_MONS; +} + void HasEnoughMonsForDoubleBattle(void) { switch (GetMonsStateToDoubles()) diff --git a/src/secret_base.c b/src/secret_base.c index 7e0c1ae10738..e7845ee148d1 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -1163,7 +1163,7 @@ const u8 *GetSecretBaseTrainerLoseText(void) void PrepSecretBaseBattleFlags(void) { TryGainNewFanFromCounter(FANCOUNTER_BATTLED_AT_BASE); - gTrainerBattleOpponent_A = TRAINER_SECRET_BASE; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_SECRET_BASE; gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_SECRET_BASE; } diff --git a/src/stack.c b/src/stack.c new file mode 100644 index 000000000000..ee304797e686 --- /dev/null +++ b/src/stack.c @@ -0,0 +1,36 @@ +#include "global.h" +#include "stack.h" +#include "malloc.h" + +void PtrStackInit(PtrStack *s) +{ + memset(s->stack, 0, STACK_SIZE * sizeof(void*)); + s->stackPtr = -1; +} + +void* PtrStackPop(PtrStack *s) +{ + if (s->stackPtr < 0) + return NULL; + + return s->stack[s->stackPtr--]; +} + +bool32 PtrStackPush(PtrStack *s, void* ptr) +{ + if (s->stackPtr + 1 >= STACK_SIZE) + return FALSE; + + s->stack[++(s->stackPtr)] = ptr; + return TRUE; +} + +const u8* PtrStackPopU8(PtrStack *s) +{ + return (const u8*)PtrStackPop(s); +} + +bool32 PtrStackPushU8(PtrStack *s, const u8* ptr) +{ + return PtrStackPush(s, (void*)ptr); +} diff --git a/src/trainer_hill.c b/src/trainer_hill.c index dd8ae78aa774..6a05fda298eb 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -864,7 +864,7 @@ void SetHillTrainerFlag(void) for (i = 0; i < HILL_TRAINERS_PER_FLOOR; i++) { - if (gSaveBlock2Ptr->frontier.trainerIds[i] == gTrainerBattleOpponent_A) + if (gSaveBlock2Ptr->frontier.trainerIds[i] == TRAINER_BATTLE_PARAM.battleOpponentA) { gSaveBlock2Ptr->frontier.trainerFlags |= 1u << (trainerIndexStart + i); break; @@ -875,7 +875,7 @@ void SetHillTrainerFlag(void) { for (i = 0; i < HILL_TRAINERS_PER_FLOOR; i++) { - if (gSaveBlock2Ptr->frontier.trainerIds[i] == gTrainerBattleOpponent_B) + if (gSaveBlock2Ptr->frontier.trainerIds[i] == TRAINER_BATTLE_PARAM.battleOpponentB) { gSaveBlock2Ptr->frontier.trainerFlags |= 1u << (trainerIndexStart + i); break; @@ -922,14 +922,14 @@ static void CreateNPCTrainerHillParty(u16 trainerId, u8 firstMonId) void FillHillTrainerParty(void) { ZeroEnemyPartyMons(); - CreateNPCTrainerHillParty(gTrainerBattleOpponent_A, 0); + CreateNPCTrainerHillParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } void FillHillTrainersParties(void) { ZeroEnemyPartyMons(); - CreateNPCTrainerHillParty(gTrainerBattleOpponent_A, 0); - CreateNPCTrainerHillParty(gTrainerBattleOpponent_B, PARTY_SIZE / 2); + CreateNPCTrainerHillParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); + CreateNPCTrainerHillParty(TRAINER_BATTLE_PARAM.battleOpponentB, PARTY_SIZE / 2); } // This function is unused, but my best guess is diff --git a/src/trainer_see.c b/src/trainer_see.c index 2582637aa186..4b34f3642bc3 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -1,6 +1,7 @@ #include "global.h" #include "battle_setup.h" #include "event_data.h" +#include "event_scripts.h" #include "event_object_movement.h" #include "field_effect.h" #include "field_player_avatar.h" @@ -354,6 +355,8 @@ static const struct SpriteTemplate sSpriteTemplate_Emote = .callback = SpriteCB_TrainerIcons }; +#define OPCODE_OFFSET 1 + // code bool8 CheckForTrainersWantingBattle(void) { @@ -387,24 +390,75 @@ bool8 CheckForTrainersWantingBattle(void) break; } - if (gNoOfApproachingTrainers == 1) + // handle battle pyramid and trainer hill until properly reworked + if (InBattlePyramid()) { - ResetTrainerOpponentIds(); - ConfigureAndSetUpOneTrainerBattle(gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId, - gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr); - gTrainerApproachedPlayer = TRUE; - return TRUE; + if (gNoOfApproachingTrainers > 0) + { + ResetTrainerOpponentIds(); + InitTrainerBattleVariables(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[0].objectEventId].localId; + BattleSetup_ConfigureFacilityTrainerBattle(TRAINER_BATTLE_PYRAMID, gApproachingTrainers[0].trainerScriptPtr + 2); + if (gNoOfApproachingTrainers > 1) + { + gApproachingTrainerId++; + gSelectedObjectEvent = gApproachingTrainers[1].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[1].objectEventId].localId; + BattleSetup_ConfigureFacilityTrainerBattle(TRAINER_BATTLE_PYRAMID, gApproachingTrainers[0].trainerScriptPtr + 2); + gApproachingTrainerId = 0; + } + ScriptContext_SetupScript(EventScript_StartTrainerApproach); + LockPlayerFieldControls(); + return TRUE; + } + } + else if (InTrainerHill()) + { + if (gNoOfApproachingTrainers > 0) + { + ResetTrainerOpponentIds(); + InitTrainerBattleVariables(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[0].objectEventId].localId; + BattleSetup_ConfigureFacilityTrainerBattle(TRAINER_BATTLE_HILL, gApproachingTrainers[0].trainerScriptPtr + 2); + if (gNoOfApproachingTrainers > 1) + { + gApproachingTrainerId++; + gSelectedObjectEvent = gApproachingTrainers[1].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[1].objectEventId].localId; + BattleSetup_ConfigureFacilityTrainerBattle(TRAINER_BATTLE_HILL, gApproachingTrainers[0].trainerScriptPtr + 2); + gApproachingTrainerId = 0; + } + ScriptContext_SetupScript(EventScript_StartTrainerApproach); + LockPlayerFieldControls(); + return TRUE; + } } - else if (gNoOfApproachingTrainers == 2) + + if (gNoOfApproachingTrainers > 0) { ResetTrainerOpponentIds(); - for (i = 0; i < gNoOfApproachingTrainers; i++, gApproachingTrainerId++) + + PtrStack trainerBattleScriptStack; + PtrStackInit(&trainerBattleScriptStack); + TrainerBattleLoadArgs(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); + if (gNoOfApproachingTrainers > 1) { - ConfigureTwoTrainersBattle(gApproachingTrainers[i].objectEventId, - gApproachingTrainers[i].trainerScriptPtr); + gApproachingTrainerId++; + TrainerBattleLoadArgsSecondTrainer(gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); + gApproachingTrainerId = 0; } - SetUpTwoTrainersBattle(); - gApproachingTrainerId = 0; + + BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); + ScriptContext_SetupScript(EventSnippet_StartTrainerApproach); + ScriptContext_PushFromStack(&trainerBattleScriptStack); + LockPlayerFieldControls(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gSelectedObjectEvent].localId; gTrainerApproachedPlayer = TRUE; return TRUE; } @@ -415,6 +469,8 @@ bool8 CheckForTrainersWantingBattle(void) } } +#undef OPCODE_OFFSET + static u8 CheckTrainer(u8 objectEventId) { const u8 *scriptPtr; @@ -446,9 +502,8 @@ static u8 CheckTrainer(u8 objectEventId) if (approachDistance != 0) { - if (scriptPtr[1] == TRAINER_BATTLE_DOUBLE - || scriptPtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE - || scriptPtr[1] == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE) + TrainerBattleParameter* temp = (TrainerBattleParameter*)(scriptPtr + 1); + if (temp->params.isDoubleBattle) { if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS) return 0; @@ -856,6 +911,25 @@ void TryPrepareSecondApproachingTrainer(void) } } +void PrepareSecondApproachingTrainer(void) +{ + if (gApproachingTrainerId == 0) + { + gApproachingTrainerId++; + UnfreezeObjectEvents(); + FreezeObjectEventsExceptOne(gApproachingTrainers[1].objectEventId); + } + else + { + gApproachingTrainerId = 0; + } +} + +bool32 TryPrepareSecondApproachingTrainer2(void) +{ + return gNoOfApproachingTrainers > 1; +} + #define sLocalId data[0] #define sMapNum data[1] #define sMapGroup data[2] diff --git a/src/union_room_battle.c b/src/union_room_battle.c index 4d5f7d827883..a6f42c835b1e 100644 --- a/src/union_room_battle.c +++ b/src/union_room_battle.c @@ -69,7 +69,7 @@ static void CB2_SetUpPartiesAndStartBattle(void) } IncrementGameStat(GAME_STAT_NUM_UNION_ROOM_BATTLES); CalculatePlayerPartyCount(); - gTrainerBattleOpponent_A = TRAINER_UNION_ROOM; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_UNION_ROOM; SetMainCallback2(CB2_InitBattle); } diff --git a/src/vs_seeker.c b/src/vs_seeker.c index 771c01dc7235..fc7d50084688 100644 --- a/src/vs_seeker.c +++ b/src/vs_seeker.c @@ -513,7 +513,7 @@ void ClearRematchMovementByTrainerId(void) struct ObjectEventTemplate *objectEventTemplates = gSaveBlock1Ptr->objectEventTemplates; struct ObjectEvent *objectEvent; - int vsSeekerDataIdx = TrainerIdToRematchTableId(gRematchTable, gTrainerBattleOpponent_A); + int vsSeekerDataIdx = TrainerIdToRematchTableId(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); if (!I_VS_SEEKER_CHARGING) return; diff --git a/test/text.c b/test/text.c index 781aaaed3ec6..92fdf35a4839 100644 --- a/test/text.c +++ b/test/text.c @@ -612,8 +612,8 @@ TEST("Battle strings fit on the battle message window") sBattlerAbilities[j] = longAbilityID; // Set Trainers - gTrainerBattleOpponent_A = 1; - gTrainerBattleOpponent_B = 1; + TRAINER_BATTLE_PARAM.battleOpponentA = 1; + TRAINER_BATTLE_PARAM.battleOpponentB = 1; // Set battler to 1, so "The opposing " is prefixed when refering to battlers. gBattleTypeFlags |= BATTLE_TYPE_TRAINER;