From 6dd666fdf8df70d65a4b45e45c61b8b178e2ce1e Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 13 Jul 2024 00:17:18 +0200 Subject: [PATCH 01/39] consolidate trainerparam globals into struct --- asm/macros/event.inc | 14 ++- data/scripts/trainer_battle.inc | 12 +-- include/battle_setup.h | 21 ++++ include/config/general.h | 2 +- include/constants/battle.h | 2 +- include/script.h | 1 + src/battle_ai_main.c | 8 +- src/battle_arena.c | 4 +- src/battle_bg.c | 10 +- src/battle_controller_link_opponent.c | 10 +- src/battle_controller_opponent.c | 20 ++-- src/battle_controller_recorded_opponent.c | 6 +- src/battle_dome.c | 18 ++-- src/battle_factory.c | 8 +- src/battle_gimmick.c | 2 +- src/battle_main.c | 30 +++--- src/battle_message.c | 52 +++++----- src/battle_palace.c | 10 +- src/battle_pike.c | 28 +++--- src/battle_pyramid.c | 6 +- src/battle_script_commands.c | 4 +- src/battle_setup.c | 115 +++++++++++++--------- src/battle_tent.c | 18 ++-- src/battle_tower.c | 68 ++++++------- src/battle_transition.c | 4 +- src/battle_util.c | 2 +- src/cable_club.c | 4 +- src/frontier_util.c | 12 +-- src/pokemon.c | 8 +- src/recorded_battle.c | 52 +++++----- src/scrcmd.c | 3 + src/script.c | 7 ++ src/secret_base.c | 2 +- src/trainer_hill.c | 10 +- src/trainer_see.c | 2 + src/union_room_battle.c | 2 +- src/vs_seeker.c | 2 +- 37 files changed, 325 insertions(+), 254 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index bab06a0da13..b4360fe5279 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -741,7 +741,19 @@ @ 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 + .byte 0x5c + .byte TRAINER_BATTLE_SINGLE @ battleMode 1 + .2byte 0 @ objEventLocalId 2 + .2byte \trainer @ battleOpponentA 2 + .4byte \intro_text @ introTextA 4 + .4byte \lose_text @ defeatTextA 4 + .4byte 0 @ retAddrA 4 + .2byte 0 @ battleOpponentB 2 + .4byte 0 @ introTextB 4 + .4byte 0 @ defeatTextB 4 + .4byte 0 @ retAddrB 4 + .4byte 0 @ victoryText 4 + .4byte 0 @ cannotBattle 4 .elseif \music == TRUE trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, 0, \intro_text, \lose_text, \event_script .else diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index 900e5da8f8a..0a4ea540675 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -118,12 +118,12 @@ 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 + @ 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 diff --git a/include/battle_setup.h b/include/battle_setup.h index a2009eea412..500b8e9e6c4 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -12,8 +12,29 @@ struct RematchTrainer u16 mapNum; }; +typedef union TrainerBattleParameterUnion +{ + struct PACKED Parameters + { + u8 battleMode; + u16 objEventLocalId; + u16 battleOpponentA; + u8* introTextA; + u8* defeatTextA; + u8* battleScriptRetAddrA; + u16 battleOpponentB; + u8* introTextB; + u8* defeatTextB; + u8* battleScriptRetAddrB; + u8* victoryText; + u8* cannotBattleText; + } params; + u8 data[sizeof(struct Parameters)]; +} TrainerBattleParameterU; + extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; +extern TrainerBattleParameterU sTrainerBattleParameter; extern u16 gTrainerBattleOpponent_A; extern u16 gTrainerBattleOpponent_B; extern u16 gPartnerTrainerId; diff --git a/include/config/general.h b/include/config/general.h index a374ee97a17..fb537b56ae7 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 1f11adbd5f4..57e7e14d93d 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 && sTrainerBattleParameter.params.battleOpponentB == 0xFFFF)) #define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER) diff --git a/include/script.h b/include/script.h index 4dc30ca74cf..5a5096bc641 100644 --- a/include/script.h +++ b/include/script.h @@ -32,6 +32,7 @@ void ScriptReturn(struct ScriptContext *ctx); u16 ScriptReadHalfword(struct ScriptContext *ctx); u32 ScriptReadWord(struct ScriptContext *ctx); u32 ScriptPeekWord(struct ScriptContext *ctx); +void ScriptConsume(struct ScriptContext *ctx, u8* buffer, u32 n); void LockPlayerFieldControls(void); void UnlockPlayerFieldControls(void); bool8 ArePlayerFieldControlsLocked(void); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a21e13b8fc0..d64aef9c6db 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -97,7 +97,7 @@ void BattleAI_SetupItems(void) { s32 i; u8 *data = (u8 *)BATTLE_HISTORY; - const u16 *items = GetTrainerItemsFromId(gTrainerBattleOpponent_A); + const u16 *items = GetTrainerItemsFromId(sTrainerBattleParameter.params.battleOpponentA); for (i = 0; i < sizeof(struct BattleHistory); i++) data[i] = 0; @@ -207,9 +207,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(sTrainerBattleParameter.params.battleOpponentA); + if (sTrainerBattleParameter.params.battleOpponentB != 0) + AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(sTrainerBattleParameter.params.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 26df519be0c..05008674d9f 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -472,7 +472,7 @@ static void InitArenaChallenge(void) gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode] = 0; SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - gTrainerBattleOpponent_A = 0; + sTrainerBattleParameter.params.battleOpponentA = 0; } static void GetArenaData(void) @@ -561,7 +561,7 @@ static void GiveArenaPrize(void) static void BufferArenaOpponentName(void) { - GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar1, sTrainerBattleParameter.params.battleOpponentA); } void DrawArenaRefereeTextBox(void) diff --git a/src/battle_bg.c b/src/battle_bg.c index 328f990653e..a591c11bada 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(sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.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 0c71d0a1da5..4e28264e259 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(sTrainerBattleParameter.params.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); } else { @@ -436,7 +436,7 @@ static void LinkOpponentHandleDrawTrainerPic(u32 battler) else { xPos = 176; - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.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 a5dc6f3af13..7c1509b9bfc 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -413,7 +413,7 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) { trainerPicId = GetSecretBaseTrainerPicIndex(); } - else if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) { trainerPicId = GetFrontierBrainTrainerPicIndex(); } @@ -422,13 +422,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId == 1) - trainerPicId = GetTrainerHillTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); else - trainerPicId = GetTrainerHillTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); } else { - trainerPicId = GetTrainerHillTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); } } else if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) @@ -436,13 +436,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(sTrainerBattleParameter.params.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); } else { - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); } } else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) @@ -452,13 +452,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId != 1) - trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_B); + trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentB); else - trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentA); } else { - trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentA); } return trainerPicId; diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index abadcc231cf..2ae6f5979b3 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -398,9 +398,9 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) { if (battler == B_POSITION_OPPONENT_LEFT) - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); + trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); + trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); } else { @@ -410,7 +410,7 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) else { xPos = 176; - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) { trainerPicId = GetUnionRoomTrainerPic(); } diff --git a/src/battle_dome.c b/src/battle_dome.c index 67b9a1e2934..6cf7141bb79 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; + sTrainerBattleParameter.params.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, sTrainerBattleParameter.params.battleOpponentA); } static void InitDomeOpponentParty(void) { CalculatePlayerPartyCount(); - CreateDomeOpponentMons(TrainerIdToTournamentId(gTrainerBattleOpponent_A)); + CreateDomeOpponentMons(TrainerIdToTournamentId(sTrainerBattleParameter.params.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(); + sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.battleOpponentA, 0); } static void SaveDomeChallenge(void) @@ -5060,9 +5060,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(sTrainerBattleParameter.params.battleOpponentA)].isEliminated = TRUE; + DOME_TRAINERS[TrainerIdToTournamentId(sTrainerBattleParameter.params.battleOpponentA)].eliminatedAt = gSaveBlock2Ptr->frontier.curChallengeBattleNum; + gSaveBlock2Ptr->frontier.domeWinningMoves[TrainerIdToTournamentId(sTrainerBattleParameter.params.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) @@ -5690,7 +5690,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(sTrainerBattleParameter.params.battleOpponentA) > TrainerIdToTournamentId(TRAINER_PLAYER)) gSpecialVar_Result = 1; else gSpecialVar_Result = 2; diff --git a/src/battle_factory.c b/src/battle_factory.c index 7d7ec7b3af5..ee08fba38dc 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; + sTrainerBattleParameter.params.battleOpponentA = 0; } static void GetBattleFactoryData(void) @@ -324,7 +324,7 @@ static void GenerateOpponentMons(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_A = trainerId; + sTrainerBattleParameter.params.battleOpponentA = trainerId; if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < FRONTIER_STAGES_PER_CHALLENGE - 1) gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = trainerId; @@ -378,7 +378,7 @@ static void GenerateOpponentMons(void) static void SetOpponentGfxVar(void) { - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); } static void SetRentalsToOpponentParty(void) @@ -837,7 +837,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 (sTrainerBattleParameter.params.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 e2d622daea4..1538d034304 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 ? sTrainerBattleParameter.params.battleOpponentB : sTrainerBattleParameter.params.battleOpponentA; const struct TrainerMon *mon = &GetTrainerPartyFromId(trainerId)[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]]; return mon->useGimmick == gimmick; } diff --git a/src/battle_main.c b/src/battle_main.c index aeea09cd786..d54f0afaf99 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -529,7 +529,7 @@ static void CB2_InitBattleInternal(void) | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL))) { - gBattleTypeFlags |= (IsTrainerDoubleBattle(gTrainerBattleOpponent_A) ? BATTLE_TYPE_DOUBLE : 0); + gBattleTypeFlags |= (IsTrainerDoubleBattle(sTrainerBattleParameter.params.battleOpponentA) ? BATTLE_TYPE_DOUBLE : 0); } InitBattleBgsVideo(); @@ -557,9 +557,9 @@ static void CB2_InitBattleInternal(void) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED))) { - CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A, TRUE); + CreateNPCTrainerParty(&gEnemyParty[0], sTrainerBattleParameter.params.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], sTrainerBattleParameter.params.battleOpponentB, FALSE); SetWildMonHeldItem(); CalculateEnemyPartyCount(); } @@ -866,7 +866,7 @@ static void CB2_HandleStartBattle(void) BufferPartyVsScreenHealth_AtStart(); SetPlayerBerryDataInBattleStruct(); - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) { gLinkPlayers[0].id = 0; gLinkPlayers[1].id = 1; @@ -1071,11 +1071,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, sTrainerBattleParameter.params.battleOpponentA); + GetFrontierTrainerName(gLinkPlayers[3].name, sTrainerBattleParameter.params.battleOpponentB); + GetBattleTowerTrainerLanguage(&language, sTrainerBattleParameter.params.battleOpponentA); gLinkPlayers[2].language = language; - GetBattleTowerTrainerLanguage(&language, gTrainerBattleOpponent_B); + GetBattleTowerTrainerLanguage(&language, sTrainerBattleParameter.params.battleOpponentB); gLinkPlayers[3].language = language; if (IsLinkTaskFinished()) @@ -1730,7 +1730,7 @@ static void CB2_HandleStartMultiBattle(void) SetMainCallback2(BattleMainCB2); if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT; + sTrainerBattleParameter.params.battleOpponentA = TRAINER_LINK_OPPONENT; gBattleTypeFlags |= BATTLE_TYPE_LINK_IN_BATTLE; } } @@ -3740,14 +3740,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(sTrainerBattleParameter.params.battleOpponentB)) { - gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_B); + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(sTrainerBattleParameter.params.battleOpponentB); gBattleStruct->startingStatusTimer = 0; // infinite } - else if (GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A)) + else if (GetTrainerStartingStatusFromId(sTrainerBattleParameter.params.battleOpponentA)) { - gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A); + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(sTrainerBattleParameter.params.battleOpponentA); gBattleStruct->startingStatusTimer = 0; // infinite } else if (B_VAR_STARTING_STATUS != 0) @@ -5282,7 +5282,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_FrontierTrainerBattleWon; - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) PlayBGM(MUS_VICTORY_GYM_LEADER); else PlayBGM(MUS_VICTORY_TRAINER); @@ -5292,7 +5292,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon; - switch (GetTrainerClassFromId(gTrainerBattleOpponent_A)) + switch (GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA)) { case TRAINER_CLASS_ELITE_FOUR: case TRAINER_CLASS_CHAMPION: diff --git a/src/battle_message.c b/src/battle_message.c index 9ae2e6aee09..4b8729a92e6 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2804,7 +2804,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1WantsToBattle; else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) stringPtr = sText_LinkTrainerWantsToBattlePause; @@ -2876,7 +2876,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 (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1SentOutPkmn; else stringPtr = sText_LinkTrainerSentOutPkmn; @@ -2897,7 +2897,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (gTrainerBattleOpponent_A == TRAINER_LINK_OPPONENT || gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_LINK_OPPONENT || gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) stringPtr = sText_LinkTrainer2WithdrewPkmn; @@ -2937,7 +2937,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) stringPtr = sText_LinkTrainerMultiSentOutPkmn; - else if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1SentOutPkmn2; else stringPtr = sText_LinkTrainerSentOutPkmn2; @@ -3005,7 +3005,7 @@ void BufferStringBattle(u16 stringID, u32 battler) break; } } - else if (gTrainerBattleOpponent_A == TRAINER_UNION_ROOM) + else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) { switch (gBattleTextBuff1[0]) { @@ -3183,13 +3183,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(sTrainerBattleParameter.params.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(sTrainerBattleParameter.params.battleOpponentB, text, multiplayerId, battler); else - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_A, text, multiplayerId, battler); + toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentA, text, multiplayerId, battler); break; } @@ -3457,10 +3457,10 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = gAbilitiesInfo[sBattlerAbilities[gEffectBattler]].name; break; case B_TXT_TRAINER1_CLASS: // trainer class name - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentA); break; case B_TXT_TRAINER1_NAME: // trainer1 name - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_A, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); + toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentA, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); break; case B_TXT_LINK_PLAYER_NAME: // link player name toCpy = gLinkPlayers[multiplayerId].name; @@ -3483,12 +3483,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) 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, sTrainerBattleParameter.params.battleOpponentA); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, gTrainerBattleOpponent_A); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, sTrainerBattleParameter.params.battleOpponentA); toCpy = gStringVar4; } else @@ -3499,12 +3499,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) 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, sTrainerBattleParameter.params.battleOpponentA); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, gTrainerBattleOpponent_A); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, sTrainerBattleParameter.params.battleOpponentA); toCpy = gStringVar4; } break; @@ -3573,20 +3573,20 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = sText_FoePkmnPrefix4; break; case B_TXT_TRAINER2_CLASS: - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_B); + toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentB); break; case B_TXT_TRAINER2_NAME: - toCpy = BattleStringGetOpponentNameByTrainerId(gTrainerBattleOpponent_B, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)); + toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentB, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)); break; case B_TXT_TRAINER2_LOSE_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, gTrainerBattleOpponent_B); + CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, sTrainerBattleParameter.params.battleOpponentB); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, gTrainerBattleOpponent_B); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, sTrainerBattleParameter.params.battleOpponentB); toCpy = gStringVar4; } else @@ -3597,12 +3597,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) case B_TXT_TRAINER2_WIN_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, gTrainerBattleOpponent_B); + CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, sTrainerBattleParameter.params.battleOpponentB); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, gTrainerBattleOpponent_B); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, sTrainerBattleParameter.params.battleOpponentB); toCpy = gStringVar4; } break; @@ -3623,13 +3623,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = gTrainerClasses[GetFrontierOpponentClass(gPartnerTrainerId)].name; break; case B_POSITION_OPPONENT_LEFT: - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentA); break; case B_POSITION_OPPONENT_RIGHT: if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_B); + toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentB); else - toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); + toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentA); break; } break; @@ -4168,19 +4168,19 @@ u32 ShouldDoTrainerSlide(u32 battler, u32 which) if (gBattlerPartyIndexes[battler] >= 3) { firstId = 3, lastId = PARTY_SIZE; - trainerId = gTrainerBattleOpponent_B; + trainerId = sTrainerBattleParameter.params.battleOpponentB; retValue = 2; } else { firstId = 0, lastId = 3; - trainerId = gTrainerBattleOpponent_A; + trainerId = sTrainerBattleParameter.params.battleOpponentA; } } else { firstId = 0, lastId = PARTY_SIZE; - trainerId = gTrainerBattleOpponent_A; + trainerId = sTrainerBattleParameter.params.battleOpponentA; } for (i = 0; i < ARRAY_COUNT(sTrainerSlides); i++) diff --git a/src/battle_palace.c b/src/battle_palace.c index a521acea2bf..9b70f443473 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; + sTrainerBattleParameter.params.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); + sTrainerBattleParameter.params.battleOpponentA = 5 *(Random() % 255) / 64u; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); } static void BufferOpponentIntroSpeech(void) { - if (gTrainerBattleOpponent_A < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore); + if (sTrainerBattleParameter.params.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].speechBefore); } static void IncrementPalaceStreak(void) diff --git a/src/battle_pike.c b/src/battle_pike.c index 3869531d209..0cf5b4cfa1e 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -1402,11 +1402,11 @@ static void PrepareOneTrainer(bool8 difficult) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1); - gTrainerBattleOpponent_A = trainerId; + sTrainerBattleParameter.params.battleOpponentA = trainerId; gFacilityTrainers = gBattleFrontierTrainers; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.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] = sTrainerBattleParameter.params.battleOpponentA; } static void PrepareTwoTrainers(void) @@ -1428,10 +1428,10 @@ static void PrepareTwoTrainers(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1); - gTrainerBattleOpponent_A = trainerId; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + sTrainerBattleParameter.params.battleOpponentA = trainerId; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.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] = sTrainerBattleParameter.params.battleOpponentA; do { @@ -1444,10 +1444,10 @@ static void PrepareTwoTrainers(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_B = trainerId; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1); + sTrainerBattleParameter.params.battleOpponentB = trainerId; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.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] = sTrainerBattleParameter.params.battleOpponentB; } static void ClearPikeTrainerIds(void) @@ -1462,13 +1462,13 @@ static void BufferTrainerIntro(void) { if (gSpecialVar_0x8005 == 0) { - if (gTrainerBattleOpponent_A < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore); + if (sTrainerBattleParameter.params.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].speechBefore); } else if (gSpecialVar_0x8005 == 1) { - if (gTrainerBattleOpponent_B < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_B].speechBefore); + if (sTrainerBattleParameter.params.battleOpponentB < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentB].speechBefore); } } @@ -1614,7 +1614,7 @@ static void InitPikeChallenge(void) if (!(gSaveBlock2Ptr->frontier.winStreakActiveFlags & sWinStreakFlags[lvlMode])) gSaveBlock2Ptr->frontier.pikeWinStreaks[lvlMode] = 0; - gTrainerBattleOpponent_A = 0; + sTrainerBattleParameter.params.battleOpponentA = 0; gBattleOutcome = 0; } diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index ce7a0526f22..7a44deca950 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -863,7 +863,7 @@ static void InitPyramidChallenge(void) } InitBattlePyramidBagCursorPosition(); - gTrainerBattleOpponent_A = 0; + sTrainerBattleParameter.params.battleOpponentA = 0; gBattleOutcome = 0; } @@ -1322,11 +1322,11 @@ bool8 GetBattlePyramidTrainerFlag(u8 eventId) void MarkApproachingPyramidTrainersAsBattled(void) { - MarkPyramidTrainerAsBattled(gTrainerBattleOpponent_A); + MarkPyramidTrainerAsBattled(sTrainerBattleParameter.params.battleOpponentA); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { gSelectedObjectEvent = GetChosenApproachingTrainerObjectEventId(1); - MarkPyramidTrainerAsBattled(gTrainerBattleOpponent_B); + MarkPyramidTrainerAsBattled(sTrainerBattleParameter.params.battleOpponentB); } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 63c6fdcf5c2..47cf0b8e2b5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7698,9 +7698,9 @@ static void Cmd_getmoneyreward(void) if (gBattleOutcome == B_OUTCOME_WON) { - money = GetTrainerMoneyToGive(gTrainerBattleOpponent_A); + money = GetTrainerMoneyToGive(sTrainerBattleParameter.params.battleOpponentA); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - money += GetTrainerMoneyToGive(gTrainerBattleOpponent_B); + money += GetTrainerMoneyToGive(sTrainerBattleParameter.params.battleOpponentB); AddMoney(&gSaveBlock1Ptr->money, money); } else diff --git a/src/battle_setup.c b/src/battle_setup.c index 41f2b9b5023..5fc61bc5d0c 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -96,10 +96,10 @@ static void HandleRematchVarsOnBattleEnd(void); static const u8 *GetIntroSpeechOfApproachingTrainer(void); static const u8 *GetTrainerCantBattleSpeech(void); -EWRAM_DATA static u16 sTrainerBattleMode = 0; + +EWRAM_DATA static u8 sTrainerBattleMode = 0; EWRAM_DATA u16 gTrainerBattleOpponent_A = 0; EWRAM_DATA u16 gTrainerBattleOpponent_B = 0; -EWRAM_DATA u16 gPartnerTrainerId = 0; EWRAM_DATA static u16 sTrainerObjectEventLocalId = 0; EWRAM_DATA static u8 *sTrainerAIntroSpeech = NULL; EWRAM_DATA static u8 *sTrainerBIntroSpeech = NULL; @@ -107,9 +107,12 @@ 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 TrainerBattleParameterU sTrainerBattleParameter = {0}; +EWRAM_DATA u16 gPartnerTrainerId = 0; +EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0; @@ -179,7 +182,7 @@ static const struct TrainerBattleParameter sOrdinaryBattleParams[] = static const struct TrainerBattleParameter sContinueScriptBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -192,7 +195,7 @@ static const struct TrainerBattleParameter sContinueScriptBattleParams[] = static const struct TrainerBattleParameter sDoubleBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -205,7 +208,7 @@ static const struct TrainerBattleParameter sDoubleBattleParams[] = static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -218,7 +221,7 @@ static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -231,7 +234,7 @@ static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -244,7 +247,7 @@ static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -259,10 +262,10 @@ static const struct TrainerBattleParameter sTrainerTwoTrainerBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_CLEAR_VAL_16BIT}, - {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerBattleParameter.params.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerBIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, @@ -896,8 +899,8 @@ u8 GetTrainerBattleTransition(void) u8 transitionType; u8 enemyLevel; u8 playerLevel; - u32 trainerId = SanitizeTrainerId(gTrainerBattleOpponent_A); - u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + u32 trainerId = SanitizeTrainerId(sTrainerBattleParameter.params.battleOpponentA); + u32 trainerClass = GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA); if (DoesTrainerHaveMugshot(trainerId)) return B_TRANSITION_MUGSHOT; @@ -1051,12 +1054,12 @@ static u8 TrainerBattleLoadArg8(const u8 *ptr) static u16 GetTrainerAFlag(void) { - return TRAINER_FLAGS_START + gTrainerBattleOpponent_A; + return TRAINER_FLAGS_START + sTrainerBattleParameter.params.battleOpponentA; } static u16 GetTrainerBFlag(void) { - return TRAINER_FLAGS_START + gTrainerBattleOpponent_B; + return TRAINER_FLAGS_START + sTrainerBattleParameter.params.battleOpponentB; } static bool32 IsPlayerDefeated(u32 battleOutcome) @@ -1079,8 +1082,8 @@ static bool32 IsPlayerDefeated(u32 battleOutcome) void ResetTrainerOpponentIds(void) { - gTrainerBattleOpponent_A = 0; - gTrainerBattleOpponent_B = 0; + sTrainerBattleParameter.params.battleOpponentA = 0; + sTrainerBattleParameter.params.battleOpponentB = 0; } static void InitTrainerBattleVariables(void) @@ -1102,6 +1105,8 @@ static void InitTrainerBattleVariables(void) sTrainerVictorySpeech = NULL; sTrainerCannotBattleSpeech = NULL; sTrainerBattleEndScript = NULL; + + memset(sTrainerBattleParameter.data, 0, sizeof(sTrainerBattleParameter)); } static inline void SetU8(void *ptr, u8 value) @@ -1159,6 +1164,22 @@ static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, co } } +void memconsume(u8* dst, const u8* src, u32 n) +{ + for (int i = 0; i < n; i++) + dst[i] = *src++; +} + +static void TrainerBattleLoadArgs_2(const u8* data) +{ + u32 n = sizeof(sTrainerBattleParameter); + u8 buffer[n]; + + memconsume(buffer, data, n); + sTrainerBattleEndScript = (u8*)data; + memcpy(sTrainerBattleParameter.data, buffer, n); +} + void SetMapVarsToTrainer(void) { if (sTrainerObjectEventLocalId != 0) @@ -1207,12 +1228,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) case TRAINER_BATTLE_REMATCH_DOUBLE: TrainerBattleLoadArgs(sDoubleBattleParams, data); SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A); + sTrainerBattleParameter.params.battleOpponentA = GetRematchTrainerId(sTrainerBattleParameter.params.battleOpponentA); return EventScript_TryDoDoubleRematchBattle; case TRAINER_BATTLE_REMATCH: TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A); + sTrainerBattleParameter.params.battleOpponentA = GetRematchTrainerId(sTrainerBattleParameter.params.battleOpponentA); return EventScript_TryDoRematchBattle; #endif //FREE_MATCH_CALL case TRAINER_BATTLE_PYRAMID: @@ -1220,12 +1241,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) { TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); + sTrainerBattleParameter.params.battleOpponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); } else { TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - gTrainerBattleOpponent_B = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); + sTrainerBattleParameter.params.battleOpponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); } return EventScript_TryDoNormalTrainerBattle; case TRAINER_BATTLE_SET_TRAINER_A: @@ -1239,12 +1260,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) { TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); - gTrainerBattleOpponent_A = LocalIdToHillTrainerId(gSpecialVar_LastTalked); + sTrainerBattleParameter.params.battleOpponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked); } else { TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - gTrainerBattleOpponent_B = LocalIdToHillTrainerId(gSpecialVar_LastTalked); + sTrainerBattleParameter.params.battleOpponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked); } return EventScript_TryDoNormalTrainerBattle; case TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO: @@ -1256,11 +1277,13 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) if (gApproachingTrainerId == 0) { TrainerBattleLoadArgs(sOrdinaryBattleParams, data); + TrainerBattleLoadArgs_2(data); SetMapVarsToTrainer(); } else { - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); + TrainerBattleLoadArgs(sOrdinaryBattleParams, data); + TrainerBattleLoadArgs_2(data); } return EventScript_TryDoNormalTrainerBattle; } @@ -1288,11 +1311,13 @@ void SetUpTwoTrainersBattle(void) LockPlayerFieldControls(); } +#define OFFSET_TRAINERID 4 bool32 GetTrainerFlagFromScriptPointer(const u8 *data) { - u32 flag = TrainerBattleLoadArg16(data + 2); + u32 flag = TrainerBattleLoadArg16(data + OFFSET_TRAINERID); return FlagGet(TRAINER_FLAGS_START + flag); } +#undef OFFSET_TRAINERID // Set trainer's movement type so they stop and remain facing that direction // Note: Only for trainers who are spoken to directly @@ -1320,7 +1345,7 @@ bool8 GetTrainerFlag(void) static void SetBattledTrainersFlags(void) { - if (gTrainerBattleOpponent_B != 0) + if (sTrainerBattleParameter.params.battleOpponentB != 0) FlagSet(GetTrainerBFlag()); FlagSet(GetTrainerAFlag()); } @@ -1440,7 +1465,7 @@ static void CB2_EndTrainerBattle(void) { HandleBattleVariantEndParty(); - if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_SECRET_BASE) { DowngradeBadPoison(); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); @@ -1466,7 +1491,7 @@ static void CB2_EndTrainerBattle(void) static void CB2_EndRematchBattle(void) { - if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_SECRET_BASE) { DowngradeBadPoison(); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); @@ -1521,8 +1546,9 @@ void ShowTrainerIntroSpeech(void) const u8 *BattleSetup_GetScriptAddrAfterBattle(void) { - if (sTrainerBattleEndScript != NULL) - return sTrainerBattleEndScript; + if (sTrainerBattleEndScript != NULL) { + return sTrainerBattleEndScript; + } else return EventScript_TestSignpostMsg; } @@ -1540,13 +1566,12 @@ const u8 *BattleSetup_GetTrainerPostBattleScript(void) } else { - if (sTrainerABattleScriptRetAddr != NULL) + if (sTrainerBattleParameter.params.battleScriptRetAddrA != NULL) { gWhichTrainerToFaceAfterBattle = 0; - return sTrainerABattleScriptRetAddr; + return sTrainerBattleParameter.params.battleScriptRetAddrA; } } - return EventScript_TryGetTrainerScript; } @@ -1561,9 +1586,9 @@ void PlayTrainerEncounterMusic(void) u16 music; if (gApproachingTrainerId == 0) - trainerId = gTrainerBattleOpponent_A; + trainerId = sTrainerBattleParameter.params.battleOpponentA; else - trainerId = gTrainerBattleOpponent_B; + trainerId = sTrainerBattleParameter.params.battleOpponentB; if (sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC && sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC) @@ -1627,19 +1652,19 @@ static const u8 *ReturnEmptyStringIfNull(const u8 *string) static const u8 *GetIntroSpeechOfApproachingTrainer(void) { if (gApproachingTrainerId == 0) - return ReturnEmptyStringIfNull(sTrainerAIntroSpeech); + return ReturnEmptyStringIfNull(sTrainerBattleParameter.params.introTextA); else - return ReturnEmptyStringIfNull(sTrainerBIntroSpeech); + return ReturnEmptyStringIfNull(sTrainerBattleParameter.params.introTextB); } const u8 *GetTrainerALoseText(void) { const u8 *string; - if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_SECRET_BASE) string = GetSecretBaseTrainerLoseText(); else - string = sTrainerADefeatSpeech; + string = sTrainerBattleParameter.params.defeatTextA; StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(string)); return gStringVar4; @@ -1658,7 +1683,7 @@ const u8 *GetTrainerWonSpeech(void) static const u8 *GetTrainerCantBattleSpeech(void) { - return ReturnEmptyStringIfNull(sTrainerCannotBattleSpeech); + return ReturnEmptyStringIfNull(sTrainerBattleParameter.params.cannotBattleText); } s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId) @@ -1897,7 +1922,7 @@ static void RegisterTrainerInMatchCall(void) { if (FlagGet(FLAG_HAS_MATCH_CALL)) { - u32 matchCallFlagId = GetTrainerMatchCallFlag(gTrainerBattleOpponent_A); + u32 matchCallFlagId = GetTrainerMatchCallFlag(sTrainerBattleParameter.params.battleOpponentA); if (matchCallFlagId != 0xFFFF) FlagSet(matchCallFlagId); } @@ -1994,15 +2019,15 @@ u16 GetLastBeatenRematchTrainerId(u16 trainerId) bool8 ShouldTryRematchBattle(void) { - if (IsFirstTrainerIdReadyForRematch(gRematchTable, gTrainerBattleOpponent_A)) + if (IsFirstTrainerIdReadyForRematch(gRematchTable, sTrainerBattleParameter.params.battleOpponentA)) return TRUE; - return WasSecondRematchWon(gRematchTable, gTrainerBattleOpponent_A); + return WasSecondRematchWon(gRematchTable, sTrainerBattleParameter.params.battleOpponentA); } bool8 IsTrainerReadyForRematch(void) { - return IsTrainerReadyForRematch_(gRematchTable, gTrainerBattleOpponent_A); + return IsTrainerReadyForRematch_(gRematchTable, sTrainerBattleParameter.params.battleOpponentA); } static void HandleRematchVarsOnBattleEnd(void) @@ -2010,7 +2035,7 @@ static void HandleRematchVarsOnBattleEnd(void) if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) && (I_VS_SEEKER_CHARGING != 0)) ClearRematchMovementByTrainerId(); - ClearTrainerWantRematchState(gRematchTable, gTrainerBattleOpponent_A); + ClearTrainerWantRematchState(gRematchTable, sTrainerBattleParameter.params.battleOpponentA); SetBattledTrainersFlags(); } diff --git a/src/battle_tent.c b/src/battle_tent.c index 8c6a94509a6..d88bc965e44 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); + sTrainerBattleParameter.params.battleOpponentA = (u32)((Random() % 255) * 5) / 64; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); } static void BufferVerdanturfTentTrainerIntro(void) { - if (gTrainerBattleOpponent_A < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore); + if (sTrainerBattleParameter.params.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].speechBefore); } static void SaveVerdanturfTentChallenge(void) @@ -216,7 +216,7 @@ static void GiveFallarborTentPrize(void) static void BufferFallarborTentTrainerName(void) { - GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar1, sTrainerBattleParameter.params.battleOpponentA); } void CallSlateportTentFunction(void) @@ -372,8 +372,8 @@ static void GenerateOpponentMons(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_A = trainerId; - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + sTrainerBattleParameter.params.battleOpponentA = trainerId; + monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].monSet; while (monSet[numMons] != 0xFFFF) numMons++; if (numMons > 8) @@ -382,9 +382,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] = sTrainerBattleParameter.params.battleOpponentA; - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].monSet; i = 0; while (i != FRONTIER_PARTY_SIZE) { diff --git a/src/battle_tower.c b/src/battle_tower.c index 2fa78c7aa61..695f8f36334 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; + sTrainerBattleParameter.params.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 (sTrainerBattleParameter.params.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]; + sTrainerBattleParameter.params.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); + sTrainerBattleParameter.params.battleOpponentA = gSaveBlock2Ptr->frontier.trainerIds[id * 2]; + sTrainerBattleParameter.params.battleOpponentB = gSaveBlock2Ptr->frontier.trainerIds[id * 2 + 1]; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentB, 1); } else if (ChooseSpecialBattleTowerTrainer()) { - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = sTrainerBattleParameter.params.battleOpponentA; } else { @@ -1000,10 +1000,10 @@ static void SetNextFacilityOpponent(void) break; } - gTrainerBattleOpponent_A = id; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + sTrainerBattleParameter.params.battleOpponentA = id; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.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] = sTrainerBattleParameter.params.battleOpponentA; } } } @@ -1547,20 +1547,20 @@ static bool8 IsFrontierTrainerFemale(u16 trainerId) void FillFrontierTrainerParty(u8 monsCount) { ZeroEnemyPartyMons(); - FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount); + FillTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0, monsCount); } void FillFrontierTrainersParties(u8 monsCount) { ZeroEnemyPartyMons(); - FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount); - FillTrainerParty(gTrainerBattleOpponent_B, 3, monsCount); + FillTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0, monsCount); + FillTrainerParty(sTrainerBattleParameter.params.battleOpponentB, 3, monsCount); } static void FillTentTrainerParty(u8 monsCount) { ZeroEnemyPartyMons(); - FillTentTrainerParty_(gTrainerBattleOpponent_A, 0, monsCount); + FillTentTrainerParty_(sTrainerBattleParameter.params.battleOpponentA, 0, monsCount); } void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst) @@ -1665,7 +1665,7 @@ static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount) { // Normal battle frontier trainer. fixedIV = GetFrontierTrainerFixedIvs(trainerId); - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].monSet; } else if (trainerId == TRAINER_EREADER) { @@ -1820,9 +1820,9 @@ static void FillFactoryTrainerParty(void) { ZeroEnemyPartyMons(); if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT) - FillFactoryFrontierTrainerParty(gTrainerBattleOpponent_A, 0); + FillFactoryFrontierTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0); else - FillFactoryTentTrainerParty(gTrainerBattleOpponent_A, 0); + FillFactoryTentTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0); } static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId) @@ -1917,9 +1917,9 @@ static void GetOpponentIntroSpeech(void) SetFacilityPtrsGetLevel(); if (gSpecialVar_0x8005) - trainerId = gTrainerBattleOpponent_B; + trainerId = sTrainerBattleParameter.params.battleOpponentB; else - trainerId = gTrainerBattleOpponent_A; + trainerId = sTrainerBattleParameter.params.battleOpponentA; #if FREE_BATTLE_TOWER_E_READER == FALSE if (trainerId == TRAINER_EREADER) @@ -2042,7 +2042,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; + sTrainerBattleParameter.params.battleOpponentA = 0; CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_E_READER)); @@ -2052,7 +2052,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 (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE); CreateTask(Task_StartBattleAfterTransition, 1); CreateTask_PlayMapChosenOrBattleBGM(0); @@ -2117,7 +2117,7 @@ void DoSpecialTrainerBattle(void) } else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer { - gTrainerBattleOpponent_B = 0xFFFF; + sTrainerBattleParameter.params.battleOpponentB = 0xFFFF; gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; } else // MULTI_BATTLE_2_VS_2 @@ -2637,10 +2637,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); + sTrainerBattleParameter.params.battleOpponentA = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2]; + sTrainerBattleParameter.params.battleOpponentB = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2 + 1]; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentB, 1); if (gReceivedRemoteLinkPlayers && gWirelessCommType == 0) gSpecialVar_Result = 4; else @@ -2682,10 +2682,10 @@ static void SetTowerInterviewData(void) if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_SINGLES) return; - GetFrontierTrainerName(text, gTrainerBattleOpponent_A); + GetFrontierTrainerName(text, sTrainerBattleParameter.params.battleOpponentA); StripExtCtrlCodes(text); StringCopy(gSaveBlock2Ptr->frontier.towerInterview.opponentName, text); - GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.towerInterview.opponentLanguage, gTrainerBattleOpponent_A); + GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.towerInterview.opponentLanguage, sTrainerBattleParameter.params.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++) @@ -3449,10 +3449,10 @@ static void SetNextBattleTentOpponent(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - gTrainerBattleOpponent_A = trainerId; - SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0); + sTrainerBattleParameter.params.battleOpponentA = trainerId; + SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.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] = sTrainerBattleParameter.params.battleOpponentA; } static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) @@ -3466,7 +3466,7 @@ static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) u32 otID = 0; u16 monId; - monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet; + monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].monSet; bfMonCount = 0; monId = monSet[bfMonCount]; diff --git a/src/battle_transition.c b/src/battle_transition.c index b2b295e16e7..cea20fb9155 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -2256,7 +2256,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(sTrainerBattleParameter.params.battleOpponentA); GetBg0TilesDst(&tilemap, &tileset); CpuSet(sEliteFour_Tileset, tileset, 0xF0); @@ -2515,7 +2515,7 @@ static void Mugshots_CreateTrainerPics(struct Task *task) { struct Sprite *opponentSprite, *playerSprite; - u8 trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); + u8 trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentA); s16 opponentRotationScales = 0; gReservedSpritePaletteCount = 10; diff --git a/src/battle_util.c b/src/battle_util.c index 99a609a5139..92e7ed6aa5a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10922,7 +10922,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 && sTrainerBattleParameter.params.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 d6a2903fd47..b712a5d3837 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; + sTrainerBattleParameter.params.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; + sTrainerBattleParameter.params.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 ca8c76a0fdf..4f66706f0c8 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -1789,7 +1789,7 @@ void ResetFrontierTrainerIds(void) static void IsTrainerFrontierBrain(void) { - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) gSpecialVar_Result = TRUE; else gSpecialVar_Result = FALSE; @@ -1840,7 +1840,7 @@ static void GiveBattlePoints(void) challengeNum = ARRAY_COUNT(sBattlePointAwards[0][0]) - 1; points = sBattlePointAwards[facility][battleMode][challengeNum]; - if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN) + if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) points += 10; gSaveBlock2Ptr->frontier.battlePoints += points; ConvertIntToDecimalStringN(gStringVar1, points, STR_CONV_MODE_LEFT_ALIGN, 2); @@ -1850,7 +1850,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 (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) { points += 10; IncrementDailyBattlePoints(10); @@ -2122,10 +2122,10 @@ static void BufferFrontierTrainerName(void) switch (gSpecialVar_0x8005) { case 0: - GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar1, sTrainerBattleParameter.params.battleOpponentA); break; case 1: - GetFrontierTrainerName(gStringVar2, gTrainerBattleOpponent_A); + GetFrontierTrainerName(gStringVar2, sTrainerBattleParameter.params.battleOpponentA); break; } } @@ -2504,7 +2504,7 @@ u16 GetFrontierBrainMonSpecies(u8 monId) void SetFrontierBrainObjEventGfx(u8 facility) { - gTrainerBattleOpponent_A = TRAINER_FRONTIER_BRAIN; + sTrainerBattleParameter.params.battleOpponentA = TRAINER_FRONTIER_BRAIN; VarSet(VAR_OBJ_GFX_ID_0, sFrontierBrainObjEventGfx[facility][0]); } diff --git a/src/pokemon.c b/src/pokemon.c index 1dc44508e3a..f9d24c9f726 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5149,7 +5149,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(sTrainerBattleParameter.params.battleOpponentA); if (friendship > 99) friendshipLevel++; @@ -5713,11 +5713,11 @@ u16 GetBattleBGM(void) u8 trainerClass; if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) - trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A); + trainerClass = GetFrontierOpponentClass(sTrainerBattleParameter.params.battleOpponentA); else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) trainerClass = TRAINER_CLASS_EXPERT; else - trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); + trainerClass = GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA); switch (trainerClass) { @@ -5736,7 +5736,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(sTrainerBattleParameter.params.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 2ac33a08a0a..b5d3a9ee8e8 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 = sTrainerBattleParameter.params.battleOpponentA; + battleSave->opponentB = sTrainerBattleParameter.params.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 (sTrainerBattleParameter.params.battleOpponentA >= TRAINER_RECORD_MIXING_FRIEND && sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].name[i]; + battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].speechWon[i]; } - battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].language; + battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].language; } - else if (gTrainerBattleOpponent_B >= TRAINER_RECORD_MIXING_FRIEND && gTrainerBattleOpponent_B < TRAINER_RECORD_MIXING_APPRENTICE) + else if (sTrainerBattleParameter.params.battleOpponentB >= TRAINER_RECORD_MIXING_FRIEND && sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].name[i]; + battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].speechWon[i]; } - battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].language; + battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[sTrainerBattleParameter.params.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 (sTrainerBattleParameter.params.battleOpponentA >= TRAINER_RECORD_MIXING_APPRENTICE) { - battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].id; + battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; + battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_APPRENTICE].language; } - else if (gTrainerBattleOpponent_B >= TRAINER_RECORD_MIXING_APPRENTICE) + else if (sTrainerBattleParameter.params.battleOpponentB >= TRAINER_RECORD_MIXING_APPRENTICE) { - battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].id; + battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.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[sTrainerBattleParameter.params.battleOpponentB - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; + battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.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; + sTrainerBattleParameter.params.battleOpponentA = 0; + sTrainerBattleParameter.params.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; + sTrainerBattleParameter.params.battleOpponentA = src->opponentA; + sTrainerBattleParameter.params.battleOpponentB = src->opponentB; gPartnerTrainerId = src->partnerId; gRecordedBattleMultiplayerId = src->multiplayerId; sLvlMode = gSaveBlock2Ptr->frontier.lvlMode; diff --git a/src/scrcmd.c b/src/scrcmd.c index b642f41ede4..f134acd1dcd 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1971,13 +1971,16 @@ bool8 ScrCmd_dotrainerbattle(struct ScriptContext *ctx) bool8 ScrCmd_gotopostbattlescript(struct ScriptContext *ctx) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "gotopostbattlescript"); ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle(); return FALSE; } bool8 ScrCmd_gotobeatenscript(struct ScriptContext *ctx) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "gotobeatenscript"); ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript(); + DebugPrintfLevel(MGBA_LOG_DEBUG, "ctx->scriptPtr: %x", ctx->scriptPtr); return FALSE; } diff --git a/src/script.c b/src/script.c index 718592691bf..3075ce958c3 100644 --- a/src/script.c +++ b/src/script.c @@ -163,6 +163,7 @@ void ScriptReturn(struct ScriptContext *ctx) ctx->scriptPtr = ScriptPop(ctx); } + u16 ScriptReadHalfword(struct ScriptContext *ctx) { u16 value = *(ctx->scriptPtr++); @@ -188,6 +189,12 @@ u32 ScriptPeekWord(struct ScriptContext *ctx) return (((((value3 << 8) + value2) << 8) + value1) << 8) + value0; } +void ScriptConsume(struct ScriptContext *ctx, u8* buffer, u32 n) +{ + for (u32 i = 0; i < n; i++) + buffer[i] = ScriptReadWord(ctx); +} + void LockPlayerFieldControls(void) { sLockFieldControls = TRUE; diff --git a/src/secret_base.c b/src/secret_base.c index 7e0c1ae1073..4e32c8bda10 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; + sTrainerBattleParameter.params.battleOpponentA = TRAINER_SECRET_BASE; gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_SECRET_BASE; } diff --git a/src/trainer_hill.c b/src/trainer_hill.c index aa7c8ee930c..a9902fe426a 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -862,7 +862,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] == sTrainerBattleParameter.params.battleOpponentA) { gSaveBlock2Ptr->frontier.trainerFlags |= gBitTable[trainerIndexStart + i]; break; @@ -873,7 +873,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] == sTrainerBattleParameter.params.battleOpponentB) { gSaveBlock2Ptr->frontier.trainerFlags |= gBitTable[trainerIndexStart + i]; break; @@ -920,14 +920,14 @@ static void CreateNPCTrainerHillParty(u16 trainerId, u8 firstMonId) void FillHillTrainerParty(void) { ZeroEnemyPartyMons(); - CreateNPCTrainerHillParty(gTrainerBattleOpponent_A, 0); + CreateNPCTrainerHillParty(sTrainerBattleParameter.params.battleOpponentA, 0); } void FillHillTrainersParties(void) { ZeroEnemyPartyMons(); - CreateNPCTrainerHillParty(gTrainerBattleOpponent_A, 0); - CreateNPCTrainerHillParty(gTrainerBattleOpponent_B, PARTY_SIZE / 2); + CreateNPCTrainerHillParty(sTrainerBattleParameter.params.battleOpponentA, 0); + CreateNPCTrainerHillParty(sTrainerBattleParameter.params.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 67ab2ebe1d2..a1537860b60 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -426,6 +426,8 @@ static u8 CheckTrainer(u8 objectEventId) else scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); + DebugPrintfLevel(MGBA_LOG_DEBUG, "scritpptr %x", scriptPtr); + if (InBattlePyramid()) { if (GetBattlePyramidTrainerFlag(objectEventId)) diff --git a/src/union_room_battle.c b/src/union_room_battle.c index 4d5f7d82788..a8c1df04576 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; + sTrainerBattleParameter.params.battleOpponentA = TRAINER_UNION_ROOM; SetMainCallback2(CB2_InitBattle); } diff --git a/src/vs_seeker.c b/src/vs_seeker.c index 30dcb74ce0c..be110bd7492 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, sTrainerBattleParameter.params.battleOpponentA); if (!I_VS_SEEKER_CHARGING) return; From 082a7c21f18248f5938c1b11e4424cac9e727fe1 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 13 Jul 2024 13:26:46 +0200 Subject: [PATCH 02/39] fix battle end script pointing at wrong address --- include/battle_setup.h | 2 +- src/battle_setup.c | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/include/battle_setup.h b/include/battle_setup.h index 500b8e9e6c4..8f1fb951f74 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -12,7 +12,7 @@ struct RematchTrainer u16 mapNum; }; -typedef union TrainerBattleParameterUnion +typedef union PACKED TrainerBattleParameterUnion { struct PACKED Parameters { diff --git a/src/battle_setup.c b/src/battle_setup.c index 5fc61bc5d0c..8c1aff129f0 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1164,20 +1164,10 @@ static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, co } } -void memconsume(u8* dst, const u8* src, u32 n) -{ - for (int i = 0; i < n; i++) - dst[i] = *src++; -} - static void TrainerBattleLoadArgs_2(const u8* data) { - u32 n = sizeof(sTrainerBattleParameter); - u8 buffer[n]; - - memconsume(buffer, data, n); - sTrainerBattleEndScript = (u8*)data; - memcpy(sTrainerBattleParameter.data, buffer, n); + memcpy(sTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); + sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameterU); } void SetMapVarsToTrainer(void) From b58ff6fce1d90f04d7b756245f9b7f6f95d947f4 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 13 Jul 2024 13:35:34 +0200 Subject: [PATCH 03/39] introduce macro for easier access to paramerter --- include/battle_setup.h | 2 + include/constants/battle.h | 2 +- src/battle_ai_main.c | 8 +-- src/battle_arena.c | 4 +- src/battle_bg.c | 10 +-- src/battle_controller_link_opponent.c | 10 +-- src/battle_controller_opponent.c | 20 +++--- src/battle_controller_recorded_opponent.c | 6 +- src/battle_dome.c | 18 +++--- src/battle_factory.c | 8 +-- src/battle_gimmick.c | 2 +- src/battle_main.c | 30 ++++----- src/battle_message.c | 52 ++++++++-------- src/battle_palace.c | 10 +-- src/battle_pike.c | 28 ++++----- src/battle_pyramid.c | 6 +- src/battle_script_commands.c | 4 +- src/battle_setup.c | 74 +++++++++++------------ src/battle_tent.c | 18 +++--- src/battle_tower.c | 68 ++++++++++----------- src/battle_transition.c | 4 +- src/battle_util.c | 2 +- src/cable_club.c | 4 +- src/frontier_util.c | 12 ++-- src/pokemon.c | 8 +-- src/recorded_battle.c | 52 ++++++++-------- src/secret_base.c | 2 +- src/trainer_hill.c | 10 +-- src/union_room_battle.c | 2 +- src/vs_seeker.c | 2 +- 30 files changed, 240 insertions(+), 238 deletions(-) diff --git a/include/battle_setup.h b/include/battle_setup.h index 8f1fb951f74..466a77cb029 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -32,6 +32,8 @@ typedef union PACKED TrainerBattleParameterUnion u8 data[sizeof(struct Parameters)]; } TrainerBattleParameterU; +#define TRAINER_BATTLE_PARAM sTrainerBattleParameter.params + extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; extern TrainerBattleParameterU sTrainerBattleParameter; diff --git a/include/constants/battle.h b/include/constants/battle.h index 57e7e14d93d..91289f718eb 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 && sTrainerBattleParameter.params.battleOpponentB == 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) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d64aef9c6db..3d6c6627e4b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -97,7 +97,7 @@ void BattleAI_SetupItems(void) { s32 i; u8 *data = (u8 *)BATTLE_HISTORY; - const u16 *items = GetTrainerItemsFromId(sTrainerBattleParameter.params.battleOpponentA); + const u16 *items = GetTrainerItemsFromId(TRAINER_BATTLE_PARAM.battleOpponentA); for (i = 0; i < sizeof(struct BattleHistory); i++) data[i] = 0; @@ -207,9 +207,9 @@ void BattleAI_SetupFlags(void) } else { - AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(sTrainerBattleParameter.params.battleOpponentA); - if (sTrainerBattleParameter.params.battleOpponentB != 0) - AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(sTrainerBattleParameter.params.battleOpponentB); + 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 05008674d9f..3af0dd4f180 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -472,7 +472,7 @@ static void InitArenaChallenge(void) gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode] = 0; SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE); - sTrainerBattleParameter.params.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetArenaData(void) @@ -561,7 +561,7 @@ static void GiveArenaPrize(void) static void BufferArenaOpponentName(void) { - GetFrontierTrainerName(gStringVar1, sTrainerBattleParameter.params.battleOpponentA); + GetFrontierTrainerName(gStringVar1, TRAINER_BATTLE_PARAM.battleOpponentA); } void DrawArenaRefereeTextBox(void) diff --git a/src/battle_bg.c b/src/battle_bg.c index a591c11bada..c364be5079d 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(sTrainerBattleParameter.params.battleOpponentA); + 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(sTrainerBattleParameter.params.battleOpponentA); + 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(sTrainerBattleParameter.params.battleOpponentA); + 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(sTrainerBattleParameter.params.battleOpponentA); + 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(sTrainerBattleParameter.params.battleOpponentA); + 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 4e28264e259..c4f391c1a91 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(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { @@ -436,7 +436,7 @@ static void LinkOpponentHandleDrawTrainerPic(u32 battler) else { xPos = 176; - if (sTrainerBattleParameter.params.battleOpponentA == 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(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); + 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 7c1509b9bfc..6e58d75ccd3 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -413,7 +413,7 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) { trainerPicId = GetSecretBaseTrainerPicIndex(); } - else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) { trainerPicId = GetFrontierBrainTrainerPicIndex(); } @@ -422,13 +422,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId == 1) - trainerPicId = GetTrainerHillTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetTrainerHillTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { - trainerPicId = GetTrainerHillTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetTrainerHillTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); } } else if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) @@ -436,13 +436,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) if (gBattleTypeFlags & (BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TOWER_LINK_MULTI)) { if (battlerId == 1) - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); } } else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) @@ -452,13 +452,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId != 1) - trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentB); + trainerPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.battleOpponentB); else - trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.battleOpponentA); } else { - trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentA); + 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 2ae6f5979b3..d45c450b88b 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -398,9 +398,9 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) { if (battler == B_POSITION_OPPONENT_LEFT) - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentA); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentA); else - trainerPicId = GetFrontierTrainerFrontSpriteId(sTrainerBattleParameter.params.battleOpponentB); + trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.battleOpponentB); } else { @@ -410,7 +410,7 @@ static void RecordedOpponentHandleDrawTrainerPic(u32 battler) else { xPos = 176; - if (sTrainerBattleParameter.params.battleOpponentA == 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 6cf7141bb79..071a6594719 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); - sTrainerBattleParameter.params.battleOpponentA = 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, sTrainerBattleParameter.params.battleOpponentA); + CopyDomeTrainerName(gStringVar2, TRAINER_BATTLE_PARAM.battleOpponentA); } static void InitDomeOpponentParty(void) { CalculatePlayerPartyCount(); - CreateDomeOpponentMons(TrainerIdToTournamentId(sTrainerBattleParameter.params.battleOpponentA)); + 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) { - sTrainerBattleParameter.params.battleOpponentA = 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(sTrainerBattleParameter.params.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void SaveDomeChallenge(void) @@ -5060,9 +5060,9 @@ static void ResolveDomeRoundWinners(void) if (gSpecialVar_0x8005 == DOME_PLAYER_WON_MATCH) { - DOME_TRAINERS[TrainerIdToTournamentId(sTrainerBattleParameter.params.battleOpponentA)].isEliminated = TRUE; - DOME_TRAINERS[TrainerIdToTournamentId(sTrainerBattleParameter.params.battleOpponentA)].eliminatedAt = gSaveBlock2Ptr->frontier.curChallengeBattleNum; - gSaveBlock2Ptr->frontier.domeWinningMoves[TrainerIdToTournamentId(sTrainerBattleParameter.params.battleOpponentA)] = 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) @@ -5690,7 +5690,7 @@ static void ReduceDomePlayerPartyToSelectedMons(void) static void GetPlayerSeededBeforeOpponent(void) { // A higher tournament ID is a worse seed - if (TrainerIdToTournamentId(sTrainerBattleParameter.params.battleOpponentA) > 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 ee08fba38dc..577dc7e3ad9 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); - sTrainerBattleParameter.params.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetBattleFactoryData(void) @@ -324,7 +324,7 @@ static void GenerateOpponentMons(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - sTrainerBattleParameter.params.battleOpponentA = trainerId; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < FRONTIER_STAGES_PER_CHALLENGE - 1) gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = trainerId; @@ -378,7 +378,7 @@ static void GenerateOpponentMons(void) static void SetOpponentGfxVar(void) { - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void SetRentalsToOpponentParty(void) @@ -837,7 +837,7 @@ u32 GetAiScriptsInBattleFactory(void) int battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE); int challengeNum = gSaveBlock2Ptr->frontier.factoryWinStreaks[battleMode][lvlMode] / FRONTIER_STAGES_PER_CHALLENGE; - if (sTrainerBattleParameter.params.battleOpponentA == 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 1538d034304..d361020f263 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 ? sTrainerBattleParameter.params.battleOpponentB : sTrainerBattleParameter.params.battleOpponentA; + 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]]; return mon->useGimmick == gimmick; } diff --git a/src/battle_main.c b/src/battle_main.c index d54f0afaf99..0c57ca705b6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -529,7 +529,7 @@ static void CB2_InitBattleInternal(void) | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL))) { - gBattleTypeFlags |= (IsTrainerDoubleBattle(sTrainerBattleParameter.params.battleOpponentA) ? BATTLE_TYPE_DOUBLE : 0); + gBattleTypeFlags |= (IsTrainerDoubleBattle(TRAINER_BATTLE_PARAM.battleOpponentA) ? BATTLE_TYPE_DOUBLE : 0); } InitBattleBgsVideo(); @@ -557,9 +557,9 @@ static void CB2_InitBattleInternal(void) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED))) { - CreateNPCTrainerParty(&gEnemyParty[0], sTrainerBattleParameter.params.battleOpponentA, 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], sTrainerBattleParameter.params.battleOpponentB, FALSE); + CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], TRAINER_BATTLE_PARAM.battleOpponentB, FALSE); SetWildMonHeldItem(); CalculateEnemyPartyCount(); } @@ -866,7 +866,7 @@ static void CB2_HandleStartBattle(void) BufferPartyVsScreenHealth_AtStart(); SetPlayerBerryDataInBattleStruct(); - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) { gLinkPlayers[0].id = 0; gLinkPlayers[1].id = 1; @@ -1071,11 +1071,11 @@ static void CB2_HandleStartMultiPartnerBattle(void) gLinkPlayers[1].id = 2; gLinkPlayers[2].id = 1; gLinkPlayers[3].id = 3; - GetFrontierTrainerName(gLinkPlayers[2].name, sTrainerBattleParameter.params.battleOpponentA); - GetFrontierTrainerName(gLinkPlayers[3].name, sTrainerBattleParameter.params.battleOpponentB); - GetBattleTowerTrainerLanguage(&language, sTrainerBattleParameter.params.battleOpponentA); + 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, sTrainerBattleParameter.params.battleOpponentB); + GetBattleTowerTrainerLanguage(&language, TRAINER_BATTLE_PARAM.battleOpponentB); gLinkPlayers[3].language = language; if (IsLinkTaskFinished()) @@ -1730,7 +1730,7 @@ static void CB2_HandleStartMultiBattle(void) SetMainCallback2(BattleMainCB2); if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - sTrainerBattleParameter.params.battleOpponentA = TRAINER_LINK_OPPONENT; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_LINK_OPPONENT; gBattleTypeFlags |= BATTLE_TYPE_LINK_IN_BATTLE; } } @@ -3740,14 +3740,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(sTrainerBattleParameter.params.battleOpponentB)) + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentB)) { - gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(sTrainerBattleParameter.params.battleOpponentB); + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentB); gBattleStruct->startingStatusTimer = 0; // infinite } - else if (GetTrainerStartingStatusFromId(sTrainerBattleParameter.params.battleOpponentA)) + else if (GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentA)) { - gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(sTrainerBattleParameter.params.battleOpponentA); + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.battleOpponentA); gBattleStruct->startingStatusTimer = 0; // infinite } else if (B_VAR_STARTING_STATUS != 0) @@ -5282,7 +5282,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_FrontierTrainerBattleWon; - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) PlayBGM(MUS_VICTORY_GYM_LEADER); else PlayBGM(MUS_VICTORY_TRAINER); @@ -5292,7 +5292,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon; - switch (GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA)) + 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 4b8729a92e6..ec007c89619 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2804,7 +2804,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1WantsToBattle; else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) stringPtr = sText_LinkTrainerWantsToBattlePause; @@ -2876,7 +2876,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK))) stringPtr = sText_Trainer1SentOutPkmn; - else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1SentOutPkmn; else stringPtr = sText_LinkTrainerSentOutPkmn; @@ -2897,7 +2897,7 @@ void BufferStringBattle(u16 stringID, u32 battler) } else { - if (sTrainerBattleParameter.params.battleOpponentA == 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; @@ -2937,7 +2937,7 @@ void BufferStringBattle(u16 stringID, u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) stringPtr = sText_LinkTrainerMultiSentOutPkmn; - else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) stringPtr = sText_Trainer1SentOutPkmn2; else stringPtr = sText_LinkTrainerSentOutPkmn2; @@ -3005,7 +3005,7 @@ void BufferStringBattle(u16 stringID, u32 battler) break; } } - else if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_UNION_ROOM) + else if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_UNION_ROOM) { switch (gBattleTextBuff1[0]) { @@ -3183,13 +3183,13 @@ static const u8 *BattleStringGetOpponentName(u8 *text, u8 multiplayerId, u8 batt switch (GetBattlerPosition(battler)) { case B_POSITION_OPPONENT_LEFT: - toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentA, 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(sTrainerBattleParameter.params.battleOpponentB, text, multiplayerId, battler); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB, text, multiplayerId, battler); else - toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentA, text, multiplayerId, battler); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA, text, multiplayerId, battler); break; } @@ -3457,10 +3457,10 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = gAbilitiesInfo[sBattlerAbilities[gEffectBattler]].name; break; case B_TXT_TRAINER1_CLASS: // trainer class name - toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentA); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; case B_TXT_TRAINER1_NAME: // trainer1 name - toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentA, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); + toCpy = BattleStringGetOpponentNameByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA, text, multiplayerId, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); break; case B_TXT_LINK_PLAYER_NAME: // link player name toCpy = gLinkPlayers[multiplayerId].name; @@ -3483,12 +3483,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) case B_TXT_TRAINER1_LOSE_TEXT: // trainerA lose text if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, sTrainerBattleParameter.params.battleOpponentA); + CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, sTrainerBattleParameter.params.battleOpponentA); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } else @@ -3499,12 +3499,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) case B_TXT_TRAINER1_WIN_TEXT: // trainerA win text if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, sTrainerBattleParameter.params.battleOpponentA); + CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, sTrainerBattleParameter.params.battleOpponentA); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, TRAINER_BATTLE_PARAM.battleOpponentA); toCpy = gStringVar4; } break; @@ -3573,20 +3573,20 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = sText_FoePkmnPrefix4; break; case B_TXT_TRAINER2_CLASS: - toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentB); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB); break; case B_TXT_TRAINER2_NAME: - toCpy = BattleStringGetOpponentNameByTrainerId(sTrainerBattleParameter.params.battleOpponentB, 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_LOSE_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, sTrainerBattleParameter.params.battleOpponentB); + CopyFrontierTrainerText(FRONTIER_PLAYER_WON_TEXT, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, sTrainerBattleParameter.params.battleOpponentB); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_WON, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } else @@ -3597,12 +3597,12 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) case B_TXT_TRAINER2_WIN_TEXT: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) { - CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, sTrainerBattleParameter.params.battleOpponentB); + CopyFrontierTrainerText(FRONTIER_PLAYER_LOST_TEXT, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) { - CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, sTrainerBattleParameter.params.battleOpponentB); + CopyTrainerHillTrainerText(TRAINER_HILL_TEXT_PLAYER_LOST, TRAINER_BATTLE_PARAM.battleOpponentB); toCpy = gStringVar4; } break; @@ -3623,13 +3623,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) toCpy = gTrainerClasses[GetFrontierOpponentClass(gPartnerTrainerId)].name; break; case B_POSITION_OPPONENT_LEFT: - toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentA); + 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(sTrainerBattleParameter.params.battleOpponentB); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentB); else - toCpy = BattleStringGetOpponentClassByTrainerId(sTrainerBattleParameter.params.battleOpponentA); + toCpy = BattleStringGetOpponentClassByTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); break; } break; @@ -4168,19 +4168,19 @@ u32 ShouldDoTrainerSlide(u32 battler, u32 which) if (gBattlerPartyIndexes[battler] >= 3) { firstId = 3, lastId = PARTY_SIZE; - trainerId = sTrainerBattleParameter.params.battleOpponentB; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentB; retValue = 2; } else { firstId = 0, lastId = 3; - trainerId = sTrainerBattleParameter.params.battleOpponentA; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; } } else { firstId = 0, lastId = PARTY_SIZE; - trainerId = sTrainerBattleParameter.params.battleOpponentA; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; } for (i = 0; i < ARRAY_COUNT(sTrainerSlides); i++) diff --git a/src/battle_palace.c b/src/battle_palace.c index 9b70f443473..a04f0bc2645 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); - sTrainerBattleParameter.params.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; } static void GetPalaceData(void) @@ -153,14 +153,14 @@ static void GetPalaceCommentId(void) static void SetPalaceOpponent(void) { - sTrainerBattleParameter.params.battleOpponentA = 5 *(Random() % 255) / 64u; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = 5 *(Random() % 255) / 64u; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void BufferOpponentIntroSpeech(void) { - if (sTrainerBattleParameter.params.battleOpponentA < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].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 0cf5b4cfa1e..d24d86e4dbe 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -1402,11 +1402,11 @@ static void PrepareOneTrainer(bool8 difficult) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1); - sTrainerBattleParameter.params.battleOpponentA = trainerId; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; gFacilityTrainers = gBattleFrontierTrainers; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < NUM_PIKE_ROOMS) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = sTrainerBattleParameter.params.battleOpponentA; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = TRAINER_BATTLE_PARAM.battleOpponentA; } static void PrepareTwoTrainers(void) @@ -1428,10 +1428,10 @@ static void PrepareTwoTrainers(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1); - sTrainerBattleParameter.params.battleOpponentA = trainerId; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 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] = sTrainerBattleParameter.params.battleOpponentA; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1] = TRAINER_BATTLE_PARAM.battleOpponentA; do { @@ -1444,10 +1444,10 @@ static void PrepareTwoTrainers(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - sTrainerBattleParameter.params.battleOpponentB = trainerId; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentB, 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] = sTrainerBattleParameter.params.battleOpponentB; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum - 2] = TRAINER_BATTLE_PARAM.battleOpponentB; } static void ClearPikeTrainerIds(void) @@ -1462,13 +1462,13 @@ static void BufferTrainerIntro(void) { if (gSpecialVar_0x8005 == 0) { - if (sTrainerBattleParameter.params.battleOpponentA < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].speechBefore); } else if (gSpecialVar_0x8005 == 1) { - if (sTrainerBattleParameter.params.battleOpponentB < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentB].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentB < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentB].speechBefore); } } @@ -1614,7 +1614,7 @@ static void InitPikeChallenge(void) if (!(gSaveBlock2Ptr->frontier.winStreakActiveFlags & sWinStreakFlags[lvlMode])) gSaveBlock2Ptr->frontier.pikeWinStreaks[lvlMode] = 0; - sTrainerBattleParameter.params.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; gBattleOutcome = 0; } diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index 7a44deca950..64028173074 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -863,7 +863,7 @@ static void InitPyramidChallenge(void) } InitBattlePyramidBagCursorPosition(); - sTrainerBattleParameter.params.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; gBattleOutcome = 0; } @@ -1322,11 +1322,11 @@ bool8 GetBattlePyramidTrainerFlag(u8 eventId) void MarkApproachingPyramidTrainersAsBattled(void) { - MarkPyramidTrainerAsBattled(sTrainerBattleParameter.params.battleOpponentA); + MarkPyramidTrainerAsBattled(TRAINER_BATTLE_PARAM.battleOpponentA); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { gSelectedObjectEvent = GetChosenApproachingTrainerObjectEventId(1); - MarkPyramidTrainerAsBattled(sTrainerBattleParameter.params.battleOpponentB); + MarkPyramidTrainerAsBattled(TRAINER_BATTLE_PARAM.battleOpponentB); } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 47cf0b8e2b5..92e65c265f1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7698,9 +7698,9 @@ static void Cmd_getmoneyreward(void) if (gBattleOutcome == B_OUTCOME_WON) { - money = GetTrainerMoneyToGive(sTrainerBattleParameter.params.battleOpponentA); + money = GetTrainerMoneyToGive(TRAINER_BATTLE_PARAM.battleOpponentA); if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - money += GetTrainerMoneyToGive(sTrainerBattleParameter.params.battleOpponentB); + money += GetTrainerMoneyToGive(TRAINER_BATTLE_PARAM.battleOpponentB); AddMoney(&gSaveBlock1Ptr->money, money); } else diff --git a/src/battle_setup.c b/src/battle_setup.c index 8c1aff129f0..8ab36b8fb97 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -182,7 +182,7 @@ static const struct TrainerBattleParameter sOrdinaryBattleParams[] = static const struct TrainerBattleParameter sContinueScriptBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -195,7 +195,7 @@ static const struct TrainerBattleParameter sContinueScriptBattleParams[] = static const struct TrainerBattleParameter sDoubleBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -208,7 +208,7 @@ static const struct TrainerBattleParameter sDoubleBattleParams[] = static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -221,7 +221,7 @@ static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -234,7 +234,7 @@ static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerBattleParameter.params.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -247,7 +247,7 @@ static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerBattleParameter.params.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, @@ -262,10 +262,10 @@ static const struct TrainerBattleParameter sTrainerTwoTrainerBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_CLEAR_VAL_16BIT}, - {&sTrainerBattleParameter.params.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&sTrainerBattleParameter.params.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&TRAINER_BATTLE_PARAM.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, {&sTrainerBIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, @@ -899,8 +899,8 @@ u8 GetTrainerBattleTransition(void) u8 transitionType; u8 enemyLevel; u8 playerLevel; - u32 trainerId = SanitizeTrainerId(sTrainerBattleParameter.params.battleOpponentA); - u32 trainerClass = GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA); + u32 trainerId = SanitizeTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (DoesTrainerHaveMugshot(trainerId)) return B_TRANSITION_MUGSHOT; @@ -1054,12 +1054,12 @@ static u8 TrainerBattleLoadArg8(const u8 *ptr) static u16 GetTrainerAFlag(void) { - return TRAINER_FLAGS_START + sTrainerBattleParameter.params.battleOpponentA; + return TRAINER_FLAGS_START + TRAINER_BATTLE_PARAM.battleOpponentA; } static u16 GetTrainerBFlag(void) { - return TRAINER_FLAGS_START + sTrainerBattleParameter.params.battleOpponentB; + return TRAINER_FLAGS_START + TRAINER_BATTLE_PARAM.battleOpponentB; } static bool32 IsPlayerDefeated(u32 battleOutcome) @@ -1082,8 +1082,8 @@ static bool32 IsPlayerDefeated(u32 battleOutcome) void ResetTrainerOpponentIds(void) { - sTrainerBattleParameter.params.battleOpponentA = 0; - sTrainerBattleParameter.params.battleOpponentB = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentB = 0; } static void InitTrainerBattleVariables(void) @@ -1218,12 +1218,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) case TRAINER_BATTLE_REMATCH_DOUBLE: TrainerBattleLoadArgs(sDoubleBattleParams, data); SetMapVarsToTrainer(); - sTrainerBattleParameter.params.battleOpponentA = GetRematchTrainerId(sTrainerBattleParameter.params.battleOpponentA); + TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); return EventScript_TryDoDoubleRematchBattle; case TRAINER_BATTLE_REMATCH: TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); - sTrainerBattleParameter.params.battleOpponentA = GetRematchTrainerId(sTrainerBattleParameter.params.battleOpponentA); + TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); return EventScript_TryDoRematchBattle; #endif //FREE_MATCH_CALL case TRAINER_BATTLE_PYRAMID: @@ -1231,12 +1231,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) { TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); - sTrainerBattleParameter.params.battleOpponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); } else { TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - sTrainerBattleParameter.params.battleOpponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); } return EventScript_TryDoNormalTrainerBattle; case TRAINER_BATTLE_SET_TRAINER_A: @@ -1250,12 +1250,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) { TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); - sTrainerBattleParameter.params.battleOpponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked); + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked); } else { TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - sTrainerBattleParameter.params.battleOpponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked); + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked); } return EventScript_TryDoNormalTrainerBattle; case TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO: @@ -1335,7 +1335,7 @@ bool8 GetTrainerFlag(void) static void SetBattledTrainersFlags(void) { - if (sTrainerBattleParameter.params.battleOpponentB != 0) + if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) FlagSet(GetTrainerBFlag()); FlagSet(GetTrainerAFlag()); } @@ -1455,7 +1455,7 @@ static void CB2_EndTrainerBattle(void) { HandleBattleVariantEndParty(); - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_SECRET_BASE) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) { DowngradeBadPoison(); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); @@ -1481,7 +1481,7 @@ static void CB2_EndTrainerBattle(void) static void CB2_EndRematchBattle(void) { - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_SECRET_BASE) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) { DowngradeBadPoison(); SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); @@ -1556,10 +1556,10 @@ const u8 *BattleSetup_GetTrainerPostBattleScript(void) } else { - if (sTrainerBattleParameter.params.battleScriptRetAddrA != NULL) + if (TRAINER_BATTLE_PARAM.battleScriptRetAddrA != NULL) { gWhichTrainerToFaceAfterBattle = 0; - return sTrainerBattleParameter.params.battleScriptRetAddrA; + return TRAINER_BATTLE_PARAM.battleScriptRetAddrA; } } return EventScript_TryGetTrainerScript; @@ -1576,9 +1576,9 @@ void PlayTrainerEncounterMusic(void) u16 music; if (gApproachingTrainerId == 0) - trainerId = sTrainerBattleParameter.params.battleOpponentA; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; else - trainerId = sTrainerBattleParameter.params.battleOpponentB; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentB; if (sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC && sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC) @@ -1642,19 +1642,19 @@ static const u8 *ReturnEmptyStringIfNull(const u8 *string) static const u8 *GetIntroSpeechOfApproachingTrainer(void) { if (gApproachingTrainerId == 0) - return ReturnEmptyStringIfNull(sTrainerBattleParameter.params.introTextA); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.introTextA); else - return ReturnEmptyStringIfNull(sTrainerBattleParameter.params.introTextB); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.introTextB); } const u8 *GetTrainerALoseText(void) { const u8 *string; - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_SECRET_BASE) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) string = GetSecretBaseTrainerLoseText(); else - string = sTrainerBattleParameter.params.defeatTextA; + string = TRAINER_BATTLE_PARAM.defeatTextA; StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(string)); return gStringVar4; @@ -1673,7 +1673,7 @@ const u8 *GetTrainerWonSpeech(void) static const u8 *GetTrainerCantBattleSpeech(void) { - return ReturnEmptyStringIfNull(sTrainerBattleParameter.params.cannotBattleText); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.cannotBattleText); } s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId) @@ -1912,7 +1912,7 @@ static void RegisterTrainerInMatchCall(void) { if (FlagGet(FLAG_HAS_MATCH_CALL)) { - u32 matchCallFlagId = GetTrainerMatchCallFlag(sTrainerBattleParameter.params.battleOpponentA); + u32 matchCallFlagId = GetTrainerMatchCallFlag(TRAINER_BATTLE_PARAM.battleOpponentA); if (matchCallFlagId != 0xFFFF) FlagSet(matchCallFlagId); } @@ -2009,15 +2009,15 @@ u16 GetLastBeatenRematchTrainerId(u16 trainerId) bool8 ShouldTryRematchBattle(void) { - if (IsFirstTrainerIdReadyForRematch(gRematchTable, sTrainerBattleParameter.params.battleOpponentA)) + if (IsFirstTrainerIdReadyForRematch(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA)) return TRUE; - return WasSecondRematchWon(gRematchTable, sTrainerBattleParameter.params.battleOpponentA); + return WasSecondRematchWon(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); } bool8 IsTrainerReadyForRematch(void) { - return IsTrainerReadyForRematch_(gRematchTable, sTrainerBattleParameter.params.battleOpponentA); + return IsTrainerReadyForRematch_(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); } static void HandleRematchVarsOnBattleEnd(void) @@ -2025,7 +2025,7 @@ static void HandleRematchVarsOnBattleEnd(void) if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) && (I_VS_SEEKER_CHARGING != 0)) ClearRematchMovementByTrainerId(); - ClearTrainerWantRematchState(gRematchTable, sTrainerBattleParameter.params.battleOpponentA); + ClearTrainerWantRematchState(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); SetBattledTrainersFlags(); } diff --git a/src/battle_tent.c b/src/battle_tent.c index d88bc965e44..b1f04e5b01e 100644 --- a/src/battle_tent.c +++ b/src/battle_tent.c @@ -127,14 +127,14 @@ static void SetVerdanturfTentPrize(void) static void SetVerdanturfTentTrainerGfx(void) { - sTrainerBattleParameter.params.battleOpponentA = (u32)((Random() % 255) * 5) / 64; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); + TRAINER_BATTLE_PARAM.battleOpponentA = (u32)((Random() % 255) * 5) / 64; + SetBattleFacilityTrainerGfxId(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void BufferVerdanturfTentTrainerIntro(void) { - if (sTrainerBattleParameter.params.battleOpponentA < FRONTIER_TRAINERS_COUNT) - FrontierSpeechToString(gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].speechBefore); + if (TRAINER_BATTLE_PARAM.battleOpponentA < FRONTIER_TRAINERS_COUNT) + FrontierSpeechToString(gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].speechBefore); } static void SaveVerdanturfTentChallenge(void) @@ -216,7 +216,7 @@ static void GiveFallarborTentPrize(void) static void BufferFallarborTentTrainerName(void) { - GetFrontierTrainerName(gStringVar1, sTrainerBattleParameter.params.battleOpponentA); + GetFrontierTrainerName(gStringVar1, TRAINER_BATTLE_PARAM.battleOpponentA); } void CallSlateportTentFunction(void) @@ -372,8 +372,8 @@ static void GenerateOpponentMons(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - sTrainerBattleParameter.params.battleOpponentA = trainerId; - monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].monSet; + TRAINER_BATTLE_PARAM.battleOpponentA = trainerId; + monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].monSet; while (monSet[numMons] != 0xFFFF) numMons++; if (numMons > 8) @@ -382,9 +382,9 @@ static void GenerateOpponentMons(void) } if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < TENT_STAGES_PER_CHALLENGE - 1) - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = sTrainerBattleParameter.params.battleOpponentA; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; - monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].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 695f8f36334..fed05b0e4d2 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); - sTrainerBattleParameter.params.battleOpponentA = 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 (sTrainerBattleParameter.params.battleOpponentA == 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) { - sTrainerBattleParameter.params.battleOpponentA = 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; - sTrainerBattleParameter.params.battleOpponentA = gSaveBlock2Ptr->frontier.trainerIds[id * 2]; - sTrainerBattleParameter.params.battleOpponentB = gSaveBlock2Ptr->frontier.trainerIds[id * 2 + 1]; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentB, 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(sTrainerBattleParameter.params.battleOpponentA, 0); - gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = sTrainerBattleParameter.params.battleOpponentA; + 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; } - sTrainerBattleParameter.params.battleOpponentA = id; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 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] = sTrainerBattleParameter.params.battleOpponentA; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; } } } @@ -1547,20 +1547,20 @@ static bool8 IsFrontierTrainerFemale(u16 trainerId) void FillFrontierTrainerParty(u8 monsCount) { ZeroEnemyPartyMons(); - FillTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0, monsCount); + FillTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0, monsCount); } void FillFrontierTrainersParties(u8 monsCount) { ZeroEnemyPartyMons(); - FillTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0, monsCount); - FillTrainerParty(sTrainerBattleParameter.params.battleOpponentB, 3, monsCount); + FillTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0, monsCount); + FillTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentB, 3, monsCount); } static void FillTentTrainerParty(u8 monsCount) { ZeroEnemyPartyMons(); - FillTentTrainerParty_(sTrainerBattleParameter.params.battleOpponentA, 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) @@ -1665,7 +1665,7 @@ static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount) { // Normal battle frontier trainer. fixedIV = GetFrontierTrainerFixedIvs(trainerId); - monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].monSet; + monSet = gFacilityTrainers[TRAINER_BATTLE_PARAM.battleOpponentA].monSet; } else if (trainerId == TRAINER_EREADER) { @@ -1820,9 +1820,9 @@ static void FillFactoryTrainerParty(void) { ZeroEnemyPartyMons(); if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT) - FillFactoryFrontierTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0); + FillFactoryFrontierTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); else - FillFactoryTentTrainerParty(sTrainerBattleParameter.params.battleOpponentA, 0); + FillFactoryTentTrainerParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId) @@ -1917,9 +1917,9 @@ static void GetOpponentIntroSpeech(void) SetFacilityPtrsGetLevel(); if (gSpecialVar_0x8005) - trainerId = sTrainerBattleParameter.params.battleOpponentB; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentB; else - trainerId = sTrainerBattleParameter.params.battleOpponentA; + trainerId = TRAINER_BATTLE_PARAM.battleOpponentA; #if FREE_BATTLE_TOWER_E_READER == FALSE if (trainerId == TRAINER_EREADER) @@ -2042,7 +2042,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; - sTrainerBattleParameter.params.battleOpponentA = 0; + TRAINER_BATTLE_PARAM.battleOpponentA = 0; CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_E_READER)); @@ -2052,7 +2052,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 (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE); CreateTask(Task_StartBattleAfterTransition, 1); CreateTask_PlayMapChosenOrBattleBGM(0); @@ -2117,7 +2117,7 @@ void DoSpecialTrainerBattle(void) } else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer { - sTrainerBattleParameter.params.battleOpponentB = 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 @@ -2637,10 +2637,10 @@ static void LoadLinkMultiOpponentsData(void) { ResetBlockReceivedFlags(); memcpy(&gSaveBlock2Ptr->frontier.trainerIds, gBlockRecvBuffer, sizeof(gSaveBlock2Ptr->frontier.trainerIds)); - sTrainerBattleParameter.params.battleOpponentA = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2]; - sTrainerBattleParameter.params.battleOpponentB = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2 + 1]; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 0); - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentB, 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 @@ -2682,10 +2682,10 @@ static void SetTowerInterviewData(void) if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_SINGLES) return; - GetFrontierTrainerName(text, sTrainerBattleParameter.params.battleOpponentA); + GetFrontierTrainerName(text, TRAINER_BATTLE_PARAM.battleOpponentA); StripExtCtrlCodes(text); StringCopy(gSaveBlock2Ptr->frontier.towerInterview.opponentName, text); - GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.towerInterview.opponentLanguage, sTrainerBattleParameter.params.battleOpponentA); + 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++) @@ -3449,10 +3449,10 @@ static void SetNextBattleTentOpponent(void) } } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum); - sTrainerBattleParameter.params.battleOpponentA = trainerId; - SetBattleFacilityTrainerGfxId(sTrainerBattleParameter.params.battleOpponentA, 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] = sTrainerBattleParameter.params.battleOpponentA; + gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = TRAINER_BATTLE_PARAM.battleOpponentA; } static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) @@ -3466,7 +3466,7 @@ static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount) u32 otID = 0; u16 monId; - monSet = gFacilityTrainers[sTrainerBattleParameter.params.battleOpponentA].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 cea20fb9155..2caa72b0527 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -2256,7 +2256,7 @@ static bool8 Mugshot_SetGfx(struct Task *task) s16 i, j; u16 *tilemap, *tileset; const u16 *mugshotsMap = sMugshotsTilemap; - u8 mugshotColor = GetTrainerMugshotColorFromId(sTrainerBattleParameter.params.battleOpponentA); + u8 mugshotColor = GetTrainerMugshotColorFromId(TRAINER_BATTLE_PARAM.battleOpponentA); GetBg0TilesDst(&tilemap, &tileset); CpuSet(sEliteFour_Tileset, tileset, 0xF0); @@ -2515,7 +2515,7 @@ static void Mugshots_CreateTrainerPics(struct Task *task) { struct Sprite *opponentSprite, *playerSprite; - u8 trainerPicId = GetTrainerPicFromId(sTrainerBattleParameter.params.battleOpponentA); + 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 92e7ed6aa5a..0574ab1cb41 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10922,7 +10922,7 @@ bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler) return FALSE; else if (GetBattlerSide(battler) != B_SIDE_PLAYER) return FALSE; - else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && sTrainerBattleParameter.params.battleOpponentA == 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 b712a5d3837..bc4e91a62d6 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(); - sTrainerBattleParameter.params.battleOpponentA = 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(); - sTrainerBattleParameter.params.battleOpponentA = 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 4f66706f0c8..d65cacc4e51 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -1789,7 +1789,7 @@ void ResetFrontierTrainerIds(void) static void IsTrainerFrontierBrain(void) { - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) gSpecialVar_Result = TRUE; else gSpecialVar_Result = FALSE; @@ -1840,7 +1840,7 @@ static void GiveBattlePoints(void) challengeNum = ARRAY_COUNT(sBattlePointAwards[0][0]) - 1; points = sBattlePointAwards[facility][battleMode][challengeNum]; - if (sTrainerBattleParameter.params.battleOpponentA == 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); @@ -1850,7 +1850,7 @@ static void GiveBattlePoints(void) points = gSaveBlock2Ptr->frontier.cardBattlePoints; points += sBattlePointAwards[facility][battleMode][challengeNum]; IncrementDailyBattlePoints(sBattlePointAwards[facility][battleMode][challengeNum]); - if (sTrainerBattleParameter.params.battleOpponentA == TRAINER_FRONTIER_BRAIN) + if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) { points += 10; IncrementDailyBattlePoints(10); @@ -2122,10 +2122,10 @@ static void BufferFrontierTrainerName(void) switch (gSpecialVar_0x8005) { case 0: - GetFrontierTrainerName(gStringVar1, sTrainerBattleParameter.params.battleOpponentA); + GetFrontierTrainerName(gStringVar1, TRAINER_BATTLE_PARAM.battleOpponentA); break; case 1: - GetFrontierTrainerName(gStringVar2, sTrainerBattleParameter.params.battleOpponentA); + GetFrontierTrainerName(gStringVar2, TRAINER_BATTLE_PARAM.battleOpponentA); break; } } @@ -2504,7 +2504,7 @@ u16 GetFrontierBrainMonSpecies(u8 monId) void SetFrontierBrainObjEventGfx(u8 facility) { - sTrainerBattleParameter.params.battleOpponentA = TRAINER_FRONTIER_BRAIN; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_FRONTIER_BRAIN; VarSet(VAR_OBJ_GFX_ID_0, sFrontierBrainObjEventGfx[facility][0]); } diff --git a/src/pokemon.c b/src/pokemon.c index f9d24c9f726..a2f17dc0217 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5149,7 +5149,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) { u8 friendshipLevel = 0; s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); - u32 opponentTrainerClass = GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA); + u32 opponentTrainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); if (friendship > 99) friendshipLevel++; @@ -5713,11 +5713,11 @@ u16 GetBattleBGM(void) u8 trainerClass; if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) - trainerClass = GetFrontierOpponentClass(sTrainerBattleParameter.params.battleOpponentA); + trainerClass = GetFrontierOpponentClass(TRAINER_BATTLE_PARAM.battleOpponentA); else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) trainerClass = TRAINER_CLASS_EXPERT; else - trainerClass = GetTrainerClassFromId(sTrainerBattleParameter.params.battleOpponentA); + trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.battleOpponentA); switch (trainerClass) { @@ -5736,7 +5736,7 @@ u16 GetBattleBGM(void) case TRAINER_CLASS_RIVAL: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) return MUS_VS_RIVAL; - if (!StringCompare(GetTrainerNameFromId(sTrainerBattleParameter.params.battleOpponentA), 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 b5d3a9ee8e8..f401178a0de 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -349,8 +349,8 @@ bool32 MoveRecordedBattleToSaveData(void) battleSave->battleFlags = sBattleFlags; } - battleSave->opponentA = sTrainerBattleParameter.params.battleOpponentA; - battleSave->opponentB = sTrainerBattleParameter.params.battleOpponentB; + 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 (sTrainerBattleParameter.params.battleOpponentA >= TRAINER_RECORD_MIXING_FRIEND && sTrainerBattleParameter.params.battleOpponentA < 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[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].name[i]; - battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[sTrainerBattleParameter.params.battleOpponentA - 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[sTrainerBattleParameter.params.battleOpponentA - 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[sTrainerBattleParameter.params.battleOpponentA - 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[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].language; + battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[TRAINER_BATTLE_PARAM.battleOpponentA - TRAINER_RECORD_MIXING_FRIEND].language; } - else if (sTrainerBattleParameter.params.battleOpponentB >= TRAINER_RECORD_MIXING_FRIEND && sTrainerBattleParameter.params.battleOpponentB < 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[sTrainerBattleParameter.params.battleOpponentB - TRAINER_RECORD_MIXING_FRIEND].name[i]; - battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[sTrainerBattleParameter.params.battleOpponentB - 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[sTrainerBattleParameter.params.battleOpponentB - 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[sTrainerBattleParameter.params.battleOpponentB - 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[sTrainerBattleParameter.params.battleOpponentB - 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 (sTrainerBattleParameter.params.battleOpponentA >= TRAINER_RECORD_MIXING_APPRENTICE) + if (TRAINER_BATTLE_PARAM.battleOpponentA >= TRAINER_RECORD_MIXING_APPRENTICE) { - battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.battleOpponentA - 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[sTrainerBattleParameter.params.battleOpponentA - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; - battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.battleOpponentA - 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 (sTrainerBattleParameter.params.battleOpponentB >= TRAINER_RECORD_MIXING_APPRENTICE) + else if (TRAINER_BATTLE_PARAM.battleOpponentB >= TRAINER_RECORD_MIXING_APPRENTICE) { - battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.battleOpponentB - 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[sTrainerBattleParameter.params.battleOpponentB - TRAINER_RECORD_MIXING_APPRENTICE].speechWon[i]; - battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[sTrainerBattleParameter.params.battleOpponentB - 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; - sTrainerBattleParameter.params.battleOpponentA = 0; - sTrainerBattleParameter.params.battleOpponentB = 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; - sTrainerBattleParameter.params.battleOpponentA = src->opponentA; - sTrainerBattleParameter.params.battleOpponentB = 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/secret_base.c b/src/secret_base.c index 4e32c8bda10..e7845ee148d 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); - sTrainerBattleParameter.params.battleOpponentA = TRAINER_SECRET_BASE; + TRAINER_BATTLE_PARAM.battleOpponentA = TRAINER_SECRET_BASE; gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_SECRET_BASE; } diff --git a/src/trainer_hill.c b/src/trainer_hill.c index a9902fe426a..22562f565da 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -862,7 +862,7 @@ void SetHillTrainerFlag(void) for (i = 0; i < HILL_TRAINERS_PER_FLOOR; i++) { - if (gSaveBlock2Ptr->frontier.trainerIds[i] == sTrainerBattleParameter.params.battleOpponentA) + if (gSaveBlock2Ptr->frontier.trainerIds[i] == TRAINER_BATTLE_PARAM.battleOpponentA) { gSaveBlock2Ptr->frontier.trainerFlags |= gBitTable[trainerIndexStart + i]; break; @@ -873,7 +873,7 @@ void SetHillTrainerFlag(void) { for (i = 0; i < HILL_TRAINERS_PER_FLOOR; i++) { - if (gSaveBlock2Ptr->frontier.trainerIds[i] == sTrainerBattleParameter.params.battleOpponentB) + if (gSaveBlock2Ptr->frontier.trainerIds[i] == TRAINER_BATTLE_PARAM.battleOpponentB) { gSaveBlock2Ptr->frontier.trainerFlags |= gBitTable[trainerIndexStart + i]; break; @@ -920,14 +920,14 @@ static void CreateNPCTrainerHillParty(u16 trainerId, u8 firstMonId) void FillHillTrainerParty(void) { ZeroEnemyPartyMons(); - CreateNPCTrainerHillParty(sTrainerBattleParameter.params.battleOpponentA, 0); + CreateNPCTrainerHillParty(TRAINER_BATTLE_PARAM.battleOpponentA, 0); } void FillHillTrainersParties(void) { ZeroEnemyPartyMons(); - CreateNPCTrainerHillParty(sTrainerBattleParameter.params.battleOpponentA, 0); - CreateNPCTrainerHillParty(sTrainerBattleParameter.params.battleOpponentB, 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/union_room_battle.c b/src/union_room_battle.c index a8c1df04576..a6f42c835b1 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(); - sTrainerBattleParameter.params.battleOpponentA = 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 be110bd7492..a8b57638e91 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, sTrainerBattleParameter.params.battleOpponentA); + int vsSeekerDataIdx = TrainerIdToRematchTableId(gRematchTable, TRAINER_BATTLE_PARAM.battleOpponentA); if (!I_VS_SEEKER_CHARGING) return; From 3ea6ea851427b47a7d7d27571a263a0adefa7ea3 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Thu, 18 Jul 2024 15:40:50 +0200 Subject: [PATCH 04/39] update other battle types --- asm/macros/battle_frontier/battle_tower.inc | 10 +- asm/macros/event.inc | 100 +++++------------- .../scripts.inc | 2 +- data/maps/LavaridgeTown_Gym_1F/scripts.inc | 16 +-- data/scripts/trainer_hill.inc | 2 +- src/battle_setup.c | 82 ++++++++------ src/trainer_see.c | 2 - 7 files changed, 90 insertions(+), 124 deletions(-) diff --git a/asm/macros/battle_frontier/battle_tower.inc b/asm/macros/battle_frontier/battle_tower.inc index b3c86955dd7..b965e2d84c7 100644 --- a/asm/macros/battle_frontier/battle_tower.inc +++ b/asm/macros/battle_frontier/battle_tower.inc @@ -115,14 +115,14 @@ .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 + trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons + trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set second trainer mons 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 + trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons multi_do MULTI_BATTLE_2_VS_1, \partnerId .endm @@ -145,8 +145,8 @@ .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 + trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons + trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set second trainer mons multi_do_fixed MULTI_BATTLE_2_VS_2, \partnerId .endm diff --git a/asm/macros/event.inc b/asm/macros/event.inc index b4360fe5279..65cbcb87b6d 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -680,84 +680,36 @@ .byte \direction .endm + NULL = 0 + NO_OBJ_ID = 0 + NO_TRAINER = 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 type:req, localId:req, trainer_a:req, intro_text_a:req, lose_text_a:req, event_script_a:req, trainer_b:req, intro_text_b:req, lose_text_b:req, event_script_b:req, victory_text:req, cannot_battle: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 + .byte \type @ battleMode + .2byte \localId @ objEventLocalId + .2byte \trainer_a @ battleOpponentA + .4byte \intro_text_a @ introTextA + .4byte \lose_text_a @ defeatTextA + .4byte \event_script_a @ retAddrA + .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 - .byte 0x5c - .byte TRAINER_BATTLE_SINGLE @ battleMode 1 - .2byte 0 @ objEventLocalId 2 - .2byte \trainer @ battleOpponentA 2 - .4byte \intro_text @ introTextA 4 - .4byte \lose_text @ defeatTextA 4 - .4byte 0 @ retAddrA 4 - .2byte 0 @ battleOpponentB 2 - .4byte 0 @ introTextB 4 - .4byte 0 @ defeatTextB 4 - .4byte 0 @ retAddrB 4 - .4byte 0 @ victoryText 4 - .4byte 0 @ cannotBattle 4 + trainerbattle TRAINER_BATTLE_SINGLE, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, NULL .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, NULL .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, NULL .endif .endm @@ -765,27 +717,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 TRAINER_BATTLE_DOUBLE, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text .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 TRAINER_BATTLE_REMATCH, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, NULL .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 TRAINER_BATTLE_REMATCH_DOUBLE, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text .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 + trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, NULL .endm @ Starts a double battle with the player against two trainers diff --git a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index ba9d9967062..fb314bba349 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 + trainerbattle TRAINER_BATTLE_PYRAMID, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL pyramid_showhint waitmessage waitbuttonpress diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index b7db13f54a0..98979e997df 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 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 TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 msgbox LavaridgeTown_Gym_B1F_Text_EliPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 04bbe05e5ad..78abfd6d4f5 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 + trainerbattle TRAINER_BATTLE_HILL, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL trainerhill_postbattletext waitmessage waitbuttonpress diff --git a/src/battle_setup.c b/src/battle_setup.c index 8ab36b8fb97..856da485555 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -116,6 +116,12 @@ EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0; +#define DebugPrintTrainerParams DebugPrintfLevel(MGBA_LOG_DEBUG, "\nmode: %d\nlocalId: %d\ntrainerA: %d\nintroA: %x\ndefeatA: %x\neventA: %x\ntrainerB: %d\nintroB: %x\ndefeatB: %x\neventB: %x\nvictory: %x\nnotBattle:%x", \ + sTrainerBattleParameter.params.battleMode, sTrainerBattleParameter.params.objEventLocalId, \ + sTrainerBattleParameter.params.battleOpponentA, sTrainerBattleParameter.params.introTextA, sTrainerBattleParameter.params.defeatTextA, sTrainerBattleParameter.params.battleScriptRetAddrA, \ + sTrainerBattleParameter.params.battleOpponentB, sTrainerBattleParameter.params.introTextB, sTrainerBattleParameter.params.defeatTextB, sTrainerBattleParameter.params.battleScriptRetAddrB, \ + sTrainerBattleParameter.params.victoryText, sTrainerBattleParameter.params.cannotBattleText) + // The first transition is used if the enemy Pokémon are lower level than our Pokémon. // Otherwise, the second transition is used. static const u8 sBattleTransitionTable_Wild[][2] = @@ -1164,6 +1170,26 @@ static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, co } } +static void TrainerBattleLoadArgsTrainerA(const u8* data) +{ + TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + + 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 void TrainerBattleLoadArgsTrainerB(const u8* data) +{ + TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + + 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 void TrainerBattleLoadArgs_2(const u8* data) { memcpy(sTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); @@ -1172,79 +1198,77 @@ static void TrainerBattleLoadArgs_2(const u8* data) void SetMapVarsToTrainer(void) { - if (sTrainerObjectEventLocalId != 0) + if (TRAINER_BATTLE_PARAM.objEventLocalId != 0) { - gSpecialVar_LastTalked = sTrainerObjectEventLocalId; - gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(sTrainerObjectEventLocalId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalId; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); } } const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) { - if (TrainerBattleLoadArg8(data) != TRAINER_BATTLE_SET_TRAINER_B) + if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_SET_TRAINER_B) InitTrainerBattleVariables(); - sTrainerBattleMode = TrainerBattleLoadArg8(data); - switch (sTrainerBattleMode) + TrainerBattleLoadArgs_2(data); + DebugPrintTrainerParams; + + switch (TRAINER_BATTLE_PARAM.battleMode) { 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(); TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); return EventScript_TryDoDoubleRematchBattle; + case TRAINER_BATTLE_REMATCH: - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); return EventScript_TryDoRematchBattle; + #endif //FREE_MATCH_CALL case TRAINER_BATTLE_PYRAMID: if (gApproachingTrainerId == 0) { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); SetMapVarsToTrainer(); TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); } else { - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); + TrainerBattleLoadArgsTrainerB(data); TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); } return EventScript_TryDoNormalTrainerBattle; + case TRAINER_BATTLE_SET_TRAINER_A: - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); + // explicit load ? return sTrainerBattleEndScript; + case TRAINER_BATTLE_SET_TRAINER_B: - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); + TrainerBattleLoadArgsTrainerB(data); // unnecessary since should already be loaded ? return sTrainerBattleEndScript; + case TRAINER_BATTLE_HILL: if (gApproachingTrainerId == 0) { @@ -1257,24 +1281,16 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); TRAINER_BATTLE_PARAM.battleOpponentB = 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) - { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - TrainerBattleLoadArgs_2(data); SetMapVarsToTrainer(); - } - else - { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - TrainerBattleLoadArgs_2(data); - } return EventScript_TryDoNormalTrainerBattle; } } diff --git a/src/trainer_see.c b/src/trainer_see.c index a1537860b60..67ab2ebe1d2 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -426,8 +426,6 @@ static u8 CheckTrainer(u8 objectEventId) else scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); - DebugPrintfLevel(MGBA_LOG_DEBUG, "scritpptr %x", scriptPtr); - if (InBattlePyramid()) { if (GetBattlePyramidTrainerFlag(objectEventId)) From 56439e7ce3f4ee9e0f3b8a8c69fcd7ea10cb2576 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 19 Jul 2024 23:10:57 +0200 Subject: [PATCH 05/39] running script snippets by pushing them to the stack first --- data/maps/Route102/scripts.inc | 1 + data/scripts/trainer_battle.inc | 25 ++++++++++++++++ include/battle_setup.h | 13 ++++++++- include/event_scripts.h | 7 +++++ include/script.h | 11 +++++++ src/battle_setup.c | 51 +++++++++++++++++++++++++++++---- src/scrcmd.c | 14 ++++++++- src/script.c | 3 +- 8 files changed, 117 insertions(+), 8 deletions(-) diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index 6131ef9e01e..b48e436e33d 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -65,6 +65,7 @@ Route102_EventScript_Rick:: Route102_EventScript_Tiana:: trainerbattle_single TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated +Route102_EventScript_TianaMsg:: msgbox Route102_Text_TianaPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index 0a4ea540675..d4dbe702e96 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -135,3 +135,28 @@ Std_MsgboxAutoclose:: waitbuttonpress release return + +EventScript_TryDoNormalTrainerBattle2:: + lock + faceplayer + setflag FLAG_SAFE_FOLLOWER_MOVEMENT + return + +EventScript_RevealTrainer2:: + applymovement VAR_LAST_TALKED, Movement_RevealTrainer + waitmovement 0 + clearflag FLAG_SAFE_FOLLOWER_MOVEMENT + return + +EventScript_GetTrainerFlag:: + specialvar VAR_RESULT, GetTrainerFlag + goto_if_ne VAR_RESULT, FALSE, EventScript_NoNormalTrainerBattle + return + +EventScript_PlayTrainerEncounterMusic:: + special PlayTrainerEncounterMusic + return + +EventScript_SetTrainerFacingDirecttion:: + special SetTrainerFacingDirection + return \ No newline at end of file diff --git a/include/battle_setup.h b/include/battle_setup.h index 466a77cb029..d57b4e75d88 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 { @@ -32,6 +33,12 @@ typedef union PACKED TrainerBattleParameterUnion u8 data[sizeof(struct Parameters)]; } TrainerBattleParameterU; +typedef struct TrainerBattleScriptStack +{ + const u8* stack[MAX_STACK_SIZE]; + s8 stackPtr; +} TrainerBattleScriptStack; + #define TRAINER_BATTLE_PARAM sTrainerBattleParameter.params extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; @@ -59,7 +66,7 @@ u8 GetSpecialBattleTransition(s32 id); void ChooseStarter(void); void ResetTrainerOpponentIds(void); void SetMapVarsToTrainer(void); -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data); +const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, TrainerBattleScriptStack *scrStack); void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript); void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript); void SetUpTwoTrainersBattle(void); @@ -97,4 +104,8 @@ s32 TrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId) s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId); u16 GetRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId); +void initStack(TrainerBattleScriptStack *scrStack); +const u8* pop(TrainerBattleScriptStack *scrStack); +bool8 push(TrainerBattleScriptStack *scrStack, const u8* ptr); + #endif // GUARD_BATTLE_SETUP_H diff --git a/include/event_scripts.h b/include/event_scripts.h index fa0bfe5c6ec..89d72c0f1d5 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -37,6 +37,13 @@ extern const u8 EventScript_TryDoNormalTrainerBattle[]; extern const u8 EventScript_TryDoDoubleRematchBattle[]; extern const u8 EventScript_TryDoRematchBattle[]; +extern const u8 EventScript_TryDoNormalTrainerBattle2[]; +extern const u8 EventScript_RevealTrainer2[]; +extern const u8 EventScript_GetTrainerFlag[]; +extern const u8 EventScript_PlayTrainerEncounterMusic[]; +extern const u8 EventScript_SetTrainerFacingDirecttion[]; +extern const u8 EventScript_ShowTrainerIntroMsg[]; + extern const u8 BerryTreeScript[]; extern const u8 gTVBravoTrainerText00[]; diff --git a/include/script.h b/include/script.h index 5a5096bc641..cd32595491f 100644 --- a/include/script.h +++ b/include/script.h @@ -21,11 +21,22 @@ struct ScriptContext #define ScriptReadByte(ctx) (*(ctx->scriptPtr++)) +#define DebugPrintScriptStack \ +do { \ + u8 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______ScriptStack________"); \ + for (i = 0; i < ctx->stackDepth; i++) { \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, ctx->stack[i]); \ + } \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______StackFloor_________"); \ +} 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); void ScriptJump(struct ScriptContext *ctx, const u8 *ptr); void ScriptCall(struct ScriptContext *ctx, const u8 *ptr); void ScriptReturn(struct ScriptContext *ctx); diff --git a/src/battle_setup.c b/src/battle_setup.c index 856da485555..fde22e97986 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -116,11 +116,12 @@ EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0; -#define DebugPrintTrainerParams DebugPrintfLevel(MGBA_LOG_DEBUG, "\nmode: %d\nlocalId: %d\ntrainerA: %d\nintroA: %x\ndefeatA: %x\neventA: %x\ntrainerB: %d\nintroB: %x\ndefeatB: %x\neventB: %x\nvictory: %x\nnotBattle:%x", \ +#define DebugPrintTrainerParams DebugPrintfLevel(MGBA_LOG_DEBUG, "\nmode: %d\nlocalId: %d\ntrainerA: %d\nintroA: %x\ndefeatA: %x\neventA: %x\ntrainerB: %d\nintroB: %x\ndefeatB: %x\neventB: %x\nvictory: %x\nnotBattle:%x\nendscript: %x\n", \ sTrainerBattleParameter.params.battleMode, sTrainerBattleParameter.params.objEventLocalId, \ sTrainerBattleParameter.params.battleOpponentA, sTrainerBattleParameter.params.introTextA, sTrainerBattleParameter.params.defeatTextA, sTrainerBattleParameter.params.battleScriptRetAddrA, \ sTrainerBattleParameter.params.battleOpponentB, sTrainerBattleParameter.params.introTextB, sTrainerBattleParameter.params.defeatTextB, sTrainerBattleParameter.params.battleScriptRetAddrB, \ - sTrainerBattleParameter.params.victoryText, sTrainerBattleParameter.params.cannotBattleText) + sTrainerBattleParameter.params.victoryText, sTrainerBattleParameter.params.cannotBattleText, \ + sTrainerBattleEndScript) // The first transition is used if the enemy Pokémon are lower level than our Pokémon. // Otherwise, the second transition is used. @@ -1205,7 +1206,7 @@ void SetMapVarsToTrainer(void) } } -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) +const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, TrainerBattleScriptStack *scrStack) { if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_SET_TRAINER_B) InitTrainerBattleVariables(); @@ -1213,6 +1214,23 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) TrainerBattleLoadArgs_2(data); DebugPrintTrainerParams; + initStack(scrStack); + push(scrStack, EventScript_TryDoNormalTrainerBattle2); + push(scrStack, EventScript_RevealTrainer2); + push(scrStack, EventScript_GetTrainerFlag); + push(scrStack, EventScript_PlayTrainerEncounterMusic); + push(scrStack, EventScript_SetTrainerFacingDirecttion); + push(scrStack, EventScript_ShowTrainerIntroMsg); + + u8 i; + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrStack______"); + for (i = 0; i < scrStack->stackPtr; i++) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, scrStack->stack[i]); + } + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrFloor______"); + + return NULL; + switch (TRAINER_BATTLE_PARAM.battleMode) { case TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT: @@ -1299,7 +1317,7 @@ void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerSc { gSelectedObjectEvent = trainerObjEventId; gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId; - BattleSetup_ConfigureTrainerBattle(trainerScript + 1); + BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL); ScriptContext_SetupScript(EventScript_StartTrainerApproach); LockPlayerFieldControls(); } @@ -1308,7 +1326,7 @@ void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript) { gSelectedObjectEvent = trainerObjEventId; gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId; - BattleSetup_ConfigureTrainerBattle(trainerScript + 1); + BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL); } void SetUpTwoTrainersBattle(void) @@ -2077,3 +2095,26 @@ u16 CountBattledRematchTeams(u16 trainerId) return i; } + +void initStack(TrainerBattleScriptStack *scrStack) +{ + memset(scrStack->stack, 0, sizeof(MAX_STACK_SIZE)); + scrStack->stackPtr = -1; +} + +const u8* pop(TrainerBattleScriptStack *scrStack) +{ + if (scrStack->stackPtr - 1 < -1) + return NULL; + + return scrStack->stack[scrStack->stackPtr--]; +} + +bool8 push(TrainerBattleScriptStack *scrStack, const u8* ptr) +{ + if (scrStack->stackPtr + 1 >= MAX_STACK_SIZE) + return FALSE; + + scrStack->stack[++(scrStack->stackPtr)] = ptr; + return TRUE; +} \ No newline at end of file diff --git a/src/scrcmd.c b/src/scrcmd.c index f134acd1dcd..cc8e4863985 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1959,7 +1959,18 @@ bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx) bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) { - ctx->scriptPtr = BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr); + TrainerBattleScriptStack scrStack; + + BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr, &scrStack); + + const u8* ptr; + while ((ptr = pop(&scrStack)) != NULL) + { + DebugPrintfLevel(MGBA_LOG_DEBUG, "script call: %x", ptr); + ScriptCall(ctx, ptr); + } + + DebugPrintScriptStack; return FALSE; } @@ -1973,6 +1984,7 @@ bool8 ScrCmd_gotopostbattlescript(struct ScriptContext *ctx) { DebugPrintfLevel(MGBA_LOG_DEBUG, "gotopostbattlescript"); ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle(); + DebugPrintfLevel(MGBA_LOG_DEBUG, "ctx->scriptPtr: %x", ctx->scriptPtr); return FALSE; } diff --git a/src/script.c b/src/script.c index 3075ce958c3..439355a4409 100644 --- a/src/script.c +++ b/src/script.c @@ -107,6 +107,7 @@ bool8 RunScriptCommand(struct ScriptContext *ctx) } cmdCode = *(ctx->scriptPtr); + //DebugPrintfLevel(MGBA_LOG_DEBUG, "code: %x, ptr: %x\n", cmdCode, ctx->scriptPtr); ctx->scriptPtr++; func = &ctx->cmdTable[cmdCode]; @@ -124,7 +125,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)) { From 9b1170c0c4951079eb3aef3782e27f346d2c2ddd Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 20 Jul 2024 00:32:38 +0200 Subject: [PATCH 06/39] actually push script snippets on the stack --- include/script.h | 1 + src/scrcmd.c | 4 +++- src/script.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/script.h b/include/script.h index cd32595491f..50c2c613f4b 100644 --- a/include/script.h +++ b/include/script.h @@ -37,6 +37,7 @@ 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); diff --git a/src/scrcmd.c b/src/scrcmd.c index cc8e4863985..b4f4f72b22f 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1967,9 +1967,11 @@ bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) while ((ptr = pop(&scrStack)) != NULL) { DebugPrintfLevel(MGBA_LOG_DEBUG, "script call: %x", ptr); - ScriptCall(ctx, ptr); + ScriptPush(ctx, ptr); } + ctx->scriptPtr = ScriptPop(ctx); + DebugPrintScriptStack; return FALSE; } diff --git a/src/script.c b/src/script.c index 439355a4409..555bbe4b040 100644 --- a/src/script.c +++ b/src/script.c @@ -139,7 +139,7 @@ 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; From bc49435b7d0c93b230b946f439eb7ff8c5013b88 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 20 Jul 2024 16:18:21 +0200 Subject: [PATCH 07/39] set up some test trainers --- data/maps/Route102/map.json | 30 ++++++++------- data/maps/Route102/scripts.inc | 2 +- data/maps/map_groups.json | 67 ---------------------------------- src/data/wild_encounters.json | 55 ++++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 88 deletions(-) diff --git a/data/maps/Route102/map.json b/data/maps/Route102/map.json index 8ad17aae4da..821a3d4c236 100644 --- a/data/maps/Route102/map.json +++ b/data/maps/Route102/map.json @@ -53,10 +53,10 @@ }, { "graphics_id": "OBJ_EVENT_GFX_BUG_CATCHER", - "x": 25, - "y": 15, + "x": 16, + "y": 2, "elevation": 3, - "movement_type": "MOVEMENT_TYPE_FACE_UP", + "movement_type": "MOVEMENT_TYPE_FACE_DOWN", "movement_range_x": 0, "movement_range_y": 0, "trainer_type": "TRAINER_TYPE_NORMAL", @@ -66,10 +66,10 @@ }, { "graphics_id": "OBJ_EVENT_GFX_LASS", - "x": 8, - "y": 7, + "x": 14, + "y": 2, "elevation": 3, - "movement_type": "MOVEMENT_TYPE_FACE_DOWN_AND_RIGHT", + "movement_type": "MOVEMENT_TYPE_FACE_DOWN", "movement_range_x": 0, "movement_range_y": 0, "trainer_type": "TRAINER_TYPE_NORMAL", @@ -131,20 +131,24 @@ }, { "graphics_id": "OBJ_EVENT_GFX_YOUNGSTER", - "x": 19, - "y": 4, + "x": 14, + "y": 5, "elevation": 3, - "movement_type": "MOVEMENT_TYPE_FACE_DOWN", - "movement_range_x": 1, - "movement_range_y": 1, + "movement_type": "MOVEMENT_TYPE_FACE_UP", + "movement_range_x": 0, + "movement_range_y": 0, "trainer_type": "TRAINER_TYPE_NORMAL", "trainer_sight_or_berry_tree_id": "3", "script": "Route102_EventScript_Allen", "flag": "0" } ], - "warp_events": [], - "coord_events": [], + "warp_events": [ + + ], + "coord_events": [ + + ], "bg_events": [ { "type": "sign", diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index b48e436e33d..4f782fc7c2c 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -59,7 +59,7 @@ Route102_EventScript_CalvinRematch:: end Route102_EventScript_Rick:: - trainerbattle_single TRAINER_RICK, Route102_Text_RickIntro, Route102_Text_RickDefeated + trainerbattle_no_intro TRAINER_RICK, Route102_Text_RickDefeated msgbox Route102_Text_RickPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/maps/map_groups.json b/data/maps/map_groups.json index ebef431b300..909fddab72b 100644 --- a/data/maps/map_groups.json +++ b/data/maps/map_groups.json @@ -620,72 +620,5 @@ ], "gMapGroup_IndoorRoute124": [ "Route124_DivingTreasureHuntersHouse" - ], - "connections_include_order": [ - "LittlerootTown", - "OldaleTown", - "DewfordTown", - "LavaridgeTown", - "FallarborTown", - "VerdanturfTown", - "PacifidlogTown", - "PetalburgCity", - "SlateportCity", - "MauvilleCity", - "RustboroCity", - "FortreeCity", - "LilycoveCity", - "MossdeepCity", - "SootopolisCity", - "EverGrandeCity", - "Route101", - "Route102", - "Route103", - "Route104", - "Route105", - "Route106", - "Route107", - "Route108", - "Route109", - "Route110", - "Route111", - "Route112", - "Route113", - "Route114", - "Route115", - "Route116", - "Route117", - "Route118", - "Route119", - "Route120", - "Route121", - "Route122", - "Route123", - "Route124", - "Route125", - "Route126", - "Route127", - "Route128", - "Route129", - "Route130", - "Route131", - "Route132", - "Route133", - "Route134", - "Underwater_Route105", - "Underwater_Route124", - "Underwater_Route125", - "Underwater_Route126", - "Underwater_Route127", - "Underwater_Route128", - "Underwater_Route129", - "SafariZone_Northwest", - "SafariZone_North", - "SafariZone_Southwest", - "SafariZone_South", - "SafariZone_Northeast", - "SafariZone_Southeast", - "BattleFrontier_OutsideWest", - "BattleFrontier_OutsideEast" ] } diff --git a/src/data/wild_encounters.json b/src/data/wild_encounters.json index 0b30c0f65bf..053c4c095f4 100755 --- a/src/data/wild_encounters.json +++ b/src/data/wild_encounters.json @@ -7,30 +7,71 @@ { "type": "land_mons", "encounter_rates": [ - 20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1 + 20, + 20, + 10, + 10, + 10, + 10, + 5, + 5, + 4, + 4, + 1, + 1 ] }, { "type": "water_mons", "encounter_rates": [ - 60, 30, 5, 4, 1 + 60, + 30, + 5, + 4, + 1 ] }, { "type": "rock_smash_mons", "encounter_rates": [ - 60, 30, 5, 4, 1 + 60, + 30, + 5, + 4, + 1 ] }, { "type": "fishing_mons", "encounter_rates": [ - 70, 30, 60, 20, 20, 40, 40, 15, 4, 1 + 70, + 30, + 60, + 20, + 20, + 40, + 40, + 15, + 4, + 1 ], "groups": { - "old_rod": [0, 1], - "good_rod": [2, 3, 4], - "super_rod": [5, 6, 7, 8, 9] + "old_rod": [ + 0, + 1 + ], + "good_rod": [ + 2, + 3, + 4 + ], + "super_rod": [ + 5, + 6, + 7, + 8, + 9 + ] } } ], From 4d7c713bb74ed7028fb907f3c5c4722039b25dbc Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Mon, 22 Jul 2024 19:54:56 +0200 Subject: [PATCH 08/39] add generic pointer stack --- include/global.h | 1 + include/stack.h | 18 ++++++++++++++++++ src/stack.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 include/stack.h create mode 100644 src/stack.c diff --git a/include/global.h b/include/global.h index a378f15a1d9..d872d9d303a 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/stack.h b/include/stack.h new file mode 100644 index 00000000000..b713706a826 --- /dev/null +++ b/include/stack.h @@ -0,0 +1,18 @@ +#ifndef GUARD_STACK_H +#define GUARD_STACK_H + +#define STACK_SIZE 0xFF + +typedef struct PtrStack +{ + void* stack[STACK_SIZE]; + s32 stackPtr; +} PtrStack; + +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 \ No newline at end of file diff --git a/src/stack.c b/src/stack.c new file mode 100644 index 00000000000..6f9ae8f5b1d --- /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 - 1 < 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); +} \ No newline at end of file From 86b7d72fdfc3ac2ee539faa9aea9022afe568c0a Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Mon, 22 Jul 2024 19:59:05 +0200 Subject: [PATCH 09/39] move to new stack, refactor trainer_see, split eventscripts --- data/scripts/trainer_battle.inc | 37 ++++++++-- data/specials.inc | 1 + include/battle_setup.h | 10 +-- include/event_scripts.h | 9 ++- include/script.h | 11 +++ include/trainer_see.h | 2 + src/battle_setup.c | 124 ++++++++++++++++++++------------ src/scrcmd.c | 15 ++-- src/script.c | 14 ++++ src/trainer_see.c | 65 ++++++++++++++--- 10 files changed, 215 insertions(+), 73 deletions(-) diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index d4dbe702e96..3df39bf8eac 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -1,6 +1,8 @@ EventScript_StartTrainerApproach:: selectapproachingtrainer lockfortrainer + return + EventScript_TrainerApproach:: special PlayTrainerEncounterMusic special DoTrainerApproach @@ -136,19 +138,23 @@ Std_MsgboxAutoclose:: release return -EventScript_TryDoNormalTrainerBattle2:: +EventScript_Lock:: lock faceplayer setflag FLAG_SAFE_FOLLOWER_MOVEMENT return +EventScript_TrainerApproach2:: + special DoTrainerApproach + return + EventScript_RevealTrainer2:: applymovement VAR_LAST_TALKED, Movement_RevealTrainer waitmovement 0 clearflag FLAG_SAFE_FOLLOWER_MOVEMENT return -EventScript_GetTrainerFlag:: +EventScript_IsTrainerFlagSet:: specialvar VAR_RESULT, GetTrainerFlag goto_if_ne VAR_RESULT, FALSE, EventScript_NoNormalTrainerBattle return @@ -157,6 +163,29 @@ EventScript_PlayTrainerEncounterMusic:: special PlayTrainerEncounterMusic return -EventScript_SetTrainerFacingDirecttion:: +EventScript_SetTrainerFacingDirection:: special SetTrainerFacingDirection - return \ No newline at end of file + return + +EventScript_ShowTrainerIntroMsg2:: + special ShowTrainerIntroSpeech + waitmessage + waitbuttonpress + return + +EventScript_PrepareSecondTrainerApproach:: + special PrepareSecondApproachingTrainer + return + +EventScript_GotoPostBattleScript:: + gotopostbattlescript + return + +EventScript_DoTrainerBattle2:: + dotrainerbattle + return + +EventScript_EndTrainerBattle2:: + gotobeatenscript + releaseall + end \ No newline at end of file diff --git a/data/specials.inc b/data/specials.inc index f02497d6039..f12f4e20e50 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -531,6 +531,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/include/battle_setup.h b/include/battle_setup.h index d57b4e75d88..21f0f786ef4 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -66,7 +66,7 @@ u8 GetSpecialBattleTransition(s32 id); void ChooseStarter(void); void ResetTrainerOpponentIds(void); void SetMapVarsToTrainer(void); -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, TrainerBattleScriptStack *scrStack); +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); @@ -97,6 +97,10 @@ bool8 ShouldTryRematchBattle(void); bool8 IsTrainerReadyForRematch(void); void ShouldTryGetTrainerScript(void); u16 CountBattledRematchTeams(u16 trainerId); +void TrainerBattleLoadArgs_2(const u8* data); +void TrainerBattleLoadArgsTrainerA(const u8* data); +void TrainerBattleLoadArgsTrainerB(const u8* data); +void TrainerBattleLoadArgsSecondTrainer(const u8* data); void DoStandardWildBattle_Debug(void); void BattleSetup_StartTrainerBattle_Debug(void); @@ -104,8 +108,4 @@ s32 TrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId) s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId); u16 GetRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId); -void initStack(TrainerBattleScriptStack *scrStack); -const u8* pop(TrainerBattleScriptStack *scrStack); -bool8 push(TrainerBattleScriptStack *scrStack, const u8* ptr); - #endif // GUARD_BATTLE_SETUP_H diff --git a/include/event_scripts.h b/include/event_scripts.h index 89d72c0f1d5..7789959578e 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -37,12 +37,19 @@ extern const u8 EventScript_TryDoNormalTrainerBattle[]; extern const u8 EventScript_TryDoDoubleRematchBattle[]; extern const u8 EventScript_TryDoRematchBattle[]; +extern const u8 EventScript_Lock[]; extern const u8 EventScript_TryDoNormalTrainerBattle2[]; extern const u8 EventScript_RevealTrainer2[]; extern const u8 EventScript_GetTrainerFlag[]; extern const u8 EventScript_PlayTrainerEncounterMusic[]; -extern const u8 EventScript_SetTrainerFacingDirecttion[]; +extern const u8 EventScript_SetTrainerFacingDirection[]; +extern const u8 EventScript_TrainerApproach2[]; +extern const u8 EventScript_PrepareSecondTrainerApproach[]; extern const u8 EventScript_ShowTrainerIntroMsg[]; +extern const u8 EventScript_ShowTrainerIntroMsg2[]; +extern const u8 EventScript_GotoPostBattleScript[]; +extern const u8 EventScript_DoTrainerBattle2[]; +extern const u8 EventScript_EndTrainerBattle2[]; extern const u8 BerryTreeScript[]; diff --git a/include/script.h b/include/script.h index 50c2c613f4b..815c84fa0e6 100644 --- a/include/script.h +++ b/include/script.h @@ -31,6 +31,16 @@ do { \ DebugPrintfLevel(MGBA_LOG_DEBUG, "_______StackFloor_________"); \ } while(0); +#define DebugPrintGlobalScriptStack \ +do { \ + u8 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______GlobalScriptStack________"); \ + for (i = 0; i < sGlobalScriptContext.stackDepth; i++) { \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, sGlobalScriptContext.stack[i]); \ + } \ + 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)); @@ -54,6 +64,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/trainer_see.h b/include/trainer_see.h index 5518a91761c..6764e5fd33c 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_setup.c b/src/battle_setup.c index fde22e97986..8eb6225078f 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1171,7 +1171,7 @@ static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, co } } -static void TrainerBattleLoadArgsTrainerA(const u8* data) +void TrainerBattleLoadArgsTrainerA(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; @@ -1181,7 +1181,7 @@ static void TrainerBattleLoadArgsTrainerA(const u8* data) TRAINER_BATTLE_PARAM.battleScriptRetAddrA = temp->params.battleScriptRetAddrA; } -static void TrainerBattleLoadArgsTrainerB(const u8* data) +void TrainerBattleLoadArgsTrainerB(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; @@ -1191,10 +1191,23 @@ static void TrainerBattleLoadArgsTrainerB(const u8* data) TRAINER_BATTLE_PARAM.battleScriptRetAddrB = temp->params.battleScriptRetAddrB; } -static void TrainerBattleLoadArgs_2(const u8* data) -{ +// loads trainer A parameter to trainer B. Used for second trainer in trainer_see.c +void TrainerBattleLoadArgsSecondTrainer(const u8* data) +{ + TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + + 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; +} + +void TrainerBattleLoadArgs_2(const u8* data) +{ + InitTrainerBattleVariables(); memcpy(sTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameterU); + DebugPrintTrainerParams; } void SetMapVarsToTrainer(void) @@ -1206,28 +1219,72 @@ void SetMapVarsToTrainer(void) } } -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, TrainerBattleScriptStack *scrStack) +#define DebugPrintTrainerBattleStack \ +do { \ + u8 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrStack______"); \ + for (i = 0; i < scrStack->stackPtr; i++) { \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, scrStack->stack[i]); \ + } \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrFloor______"); \ +} while(0) + + +const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching) { + /* if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_SET_TRAINER_B) InitTrainerBattleVariables(); - - TrainerBattleLoadArgs_2(data); + */ + DebugPrintTrainerParams; - initStack(scrStack); - push(scrStack, EventScript_TryDoNormalTrainerBattle2); - push(scrStack, EventScript_RevealTrainer2); - push(scrStack, EventScript_GetTrainerFlag); - push(scrStack, EventScript_PlayTrainerEncounterMusic); - push(scrStack, EventScript_SetTrainerFacingDirecttion); - push(scrStack, EventScript_ShowTrainerIntroMsg); + if (isApproaching) { + PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); + PtrStackPushU8(scrStack, EventScript_TrainerApproach2); + PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); + if (TryPrepareSecondApproachingTrainer2()) { + PtrStackPushU8(scrStack, EventScript_PrepareSecondTrainerApproach); + PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); + PtrStackPushU8(scrStack, EventScript_TrainerApproach2); + PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); + } + PtrStackPushU8(scrStack, EventScript_DoTrainerBattle2); + PtrStackPushU8(scrStack, EventScript_EndTrainerBattle2); + return NULL; + } - u8 i; - DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrStack______"); - for (i = 0; i < scrStack->stackPtr; i++) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, scrStack->stack[i]); + PtrStackPushU8(scrStack, EventScript_Lock); + PtrStackPushU8(scrStack, EventScript_RevealTrainer2); + + if (GetTrainerFlag()) + { + PtrStackPushU8(scrStack, EventScript_GotoPostBattleScript); + return NULL; } - DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrFloor______"); + + if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC + && TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC) + { + PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); + } + + PtrStackPushU8(scrStack, EventScript_SetTrainerFacingDirection); + + if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT) + { + PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); + } + + if (gNoOfApproachingTrainers > 1) + { + PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); + PtrStackPushU8(scrStack, EventScript_TrainerApproach2); + PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); + } + + PtrStackPushU8(scrStack, EventScript_DoTrainerBattle2); + PtrStackPushU8(scrStack, EventScript_EndTrainerBattle2); return NULL; @@ -1317,7 +1374,7 @@ void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerSc { gSelectedObjectEvent = trainerObjEventId; gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId; - BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL); + BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL, TRUE); ScriptContext_SetupScript(EventScript_StartTrainerApproach); LockPlayerFieldControls(); } @@ -1326,7 +1383,7 @@ void ConfigureTwoTrainersBattle(u8 trainerObjEventId, const u8 *trainerScript) { gSelectedObjectEvent = trainerObjEventId; gSpecialVar_LastTalked = gObjectEvents[trainerObjEventId].localId; - BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL); + BattleSetup_ConfigureTrainerBattle(trainerScript + 1, NULL, TRUE); } void SetUpTwoTrainersBattle(void) @@ -1696,7 +1753,7 @@ const u8 *GetTrainerALoseText(void) const u8 *GetTrainerBLoseText(void) { - StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(sTrainerBDefeatSpeech)); + StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.defeatTextB)); return gStringVar4; } @@ -2095,26 +2152,3 @@ u16 CountBattledRematchTeams(u16 trainerId) return i; } - -void initStack(TrainerBattleScriptStack *scrStack) -{ - memset(scrStack->stack, 0, sizeof(MAX_STACK_SIZE)); - scrStack->stackPtr = -1; -} - -const u8* pop(TrainerBattleScriptStack *scrStack) -{ - if (scrStack->stackPtr - 1 < -1) - return NULL; - - return scrStack->stack[scrStack->stackPtr--]; -} - -bool8 push(TrainerBattleScriptStack *scrStack, const u8* ptr) -{ - if (scrStack->stackPtr + 1 >= MAX_STACK_SIZE) - return FALSE; - - scrStack->stack[++(scrStack->stackPtr)] = ptr; - return TRUE; -} \ No newline at end of file diff --git a/src/scrcmd.c b/src/scrcmd.c index b4f4f72b22f..870cde13501 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1959,20 +1959,21 @@ bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx) bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) { - TrainerBattleScriptStack scrStack; + PtrStack trainerBattleScriptStack; + PtrStackInit(&trainerBattleScriptStack); - BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr, &scrStack); + TrainerBattleLoadArgs_2(ctx->scriptPtr); + BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr, &trainerBattleScriptStack, FALSE); const u8* ptr; - while ((ptr = pop(&scrStack)) != NULL) + while ((ptr = PtrStackPopU8(&trainerBattleScriptStack)) != NULL) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "script call: %x", ptr); ScriptPush(ctx, ptr); } ctx->scriptPtr = ScriptPop(ctx); - DebugPrintScriptStack; + //DebugPrintScriptStack; return FALSE; } @@ -1984,17 +1985,13 @@ bool8 ScrCmd_dotrainerbattle(struct ScriptContext *ctx) bool8 ScrCmd_gotopostbattlescript(struct ScriptContext *ctx) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "gotopostbattlescript"); ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle(); - DebugPrintfLevel(MGBA_LOG_DEBUG, "ctx->scriptPtr: %x", ctx->scriptPtr); return FALSE; } bool8 ScrCmd_gotobeatenscript(struct ScriptContext *ctx) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "gotobeatenscript"); ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript(); - DebugPrintfLevel(MGBA_LOG_DEBUG, "ctx->scriptPtr: %x", ctx->scriptPtr); return FALSE; } diff --git a/src/script.c b/src/script.c index 555bbe4b040..d5df9feb0f8 100644 --- a/src/script.c +++ b/src/script.c @@ -244,6 +244,7 @@ bool8 ScriptContext_RunScript(void) LockPlayerFieldControls(); + //DebugPrintGlobalScriptStack; if (!RunScriptCommand(&sGlobalScriptContext)) { sGlobalScriptContextStatus = CONTEXT_SHUTDOWN; @@ -276,6 +277,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/trainer_see.c b/src/trainer_see.c index 67ab2ebe1d2..98871c14b9d 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,23 +390,43 @@ bool8 CheckForTrainersWantingBattle(void) break; } + //DebugPrintfLevel(MGBA_LOG_DEBUG, "NoApprTrainers: %d", gNoOfApproachingTrainers); + if (gNoOfApproachingTrainers == 1) { ResetTrainerOpponentIds(); - ConfigureAndSetUpOneTrainerBattle(gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId, - gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr); + + PtrStack trainerBattleScriptStack; + PtrStackInit(&trainerBattleScriptStack); + TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); + + BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); + ScriptContext_SetupScript(EventScript_StartTrainerApproach); + ScriptContext_PushFromStack(&trainerBattleScriptStack); + LockPlayerFieldControls(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gSelectedObjectEvent].localId; gTrainerApproachedPlayer = TRUE; return TRUE; } else if (gNoOfApproachingTrainers == 2) - { + { ResetTrainerOpponentIds(); - for (i = 0; i < gNoOfApproachingTrainers; i++, gApproachingTrainerId++) - { - ConfigureTwoTrainersBattle(gApproachingTrainers[i].objectEventId, - gApproachingTrainers[i].trainerScriptPtr); - } - SetUpTwoTrainersBattle(); + + PtrStack trainerBattleScriptStack; + PtrStackInit(&trainerBattleScriptStack); + TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); + TrainerBattleLoadArgsSecondTrainer (gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); + + BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); + ScriptContext_SetupScript(EventScript_StartTrainerApproach); + ScriptContext_PushFromStack(&trainerBattleScriptStack); + + LockPlayerFieldControls(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gSelectedObjectEvent].localId; gApproachingTrainerId = 0; gTrainerApproachedPlayer = TRUE; return TRUE; @@ -415,6 +438,8 @@ bool8 CheckForTrainersWantingBattle(void) } } +#undef OPCODE_OFFSET + static u8 CheckTrainer(u8 objectEventId) { const u8 *scriptPtr; @@ -425,6 +450,8 @@ static u8 CheckTrainer(u8 objectEventId) scriptPtr = GetTrainerHillTrainerScript(); else scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); + + //DebugPrintfLevel(MGBA_LOG_DEBUG, "script ptr: %x", scriptPtr); if (InBattlePyramid()) { @@ -856,6 +883,26 @@ void TryPrepareSecondApproachingTrainer(void) } } +void PrepareSecondApproachingTrainer(void) +{ + if (gApproachingTrainerId == 0) + { + gApproachingTrainerId++; + UnfreezeObjectEvents(); + FreezeObjectEventsExceptOne(gApproachingTrainers[1].objectEventId); + } + else + { + gApproachingTrainerId = 0; + } +} + +bool32 TryPrepareSecondApproachingTrainer2(void) +{ + DebugPrintfLevel(MGBA_LOG_DEBUG, "no appr: %d, id: %d", gNoOfApproachingTrainers, gApproachingTrainerId); + return gNoOfApproachingTrainers > 1; +} + #define sLocalId data[0] #define sMapNum data[1] #define sMapGroup data[2] From 5789d767bd6a44ed08f74642df27091de90b7f29 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Thu, 25 Jul 2024 13:43:35 +0200 Subject: [PATCH 10/39] fix stack not popping last element --- include/script.h | 8 ++++---- src/battle_setup.c | 8 ++++---- src/scrcmd.c | 2 ++ src/stack.c | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/script.h b/include/script.h index 815c84fa0e6..1248b1dfa2a 100644 --- a/include/script.h +++ b/include/script.h @@ -25,8 +25,8 @@ struct ScriptContext do { \ u8 i; \ DebugPrintfLevel(MGBA_LOG_DEBUG, "_______ScriptStack________"); \ - for (i = 0; i < ctx->stackDepth; i++) { \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, ctx->stack[i]); \ + 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); @@ -35,8 +35,8 @@ do { \ do { \ u8 i; \ DebugPrintfLevel(MGBA_LOG_DEBUG, "_______GlobalScriptStack________"); \ - for (i = 0; i < sGlobalScriptContext.stackDepth; i++) { \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, sGlobalScriptContext.stack[i]); \ + 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); diff --git a/src/battle_setup.c b/src/battle_setup.c index 8eb6225078f..6b4e99a04b8 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1221,12 +1221,12 @@ void SetMapVarsToTrainer(void) #define DebugPrintTrainerBattleStack \ do { \ - u8 i; \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrStack______"); \ - for (i = 0; i < scrStack->stackPtr; i++) { \ + s16 i; \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______TrainerScriptStack______"); \ + for (i = scrStack->stackPtr; i > -1; i--) { \ DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, scrStack->stack[i]); \ } \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "_______scrFloor______"); \ + DebugPrintfLevel(MGBA_LOG_DEBUG, "_______TrainerScriptFloor______"); \ } while(0) diff --git a/src/scrcmd.c b/src/scrcmd.c index 870cde13501..533131c6857 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1970,6 +1970,8 @@ bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) { ScriptPush(ctx, ptr); } + + DebugPrintScriptStack; ctx->scriptPtr = ScriptPop(ctx); diff --git a/src/stack.c b/src/stack.c index 6f9ae8f5b1d..2bcba5be050 100644 --- a/src/stack.c +++ b/src/stack.c @@ -10,7 +10,7 @@ void PtrStackInit(PtrStack *s) void* PtrStackPop(PtrStack *s) { - if (s->stackPtr - 1 < 0) + if (s->stackPtr < 0) return NULL; return s->stack[s->stackPtr--]; From 1c338828927cf64c7c4979ba566b4372e767a883 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Thu, 25 Jul 2024 13:46:15 +0200 Subject: [PATCH 11/39] replace battle type with flags. first double and rematch integration --- asm/macros/battle_frontier/battle_tower.inc | 12 +- asm/macros/event.inc | 32 +++-- .../scripts.inc | 2 +- data/maps/LavaridgeTown_Gym_1F/scripts.inc | 16 +-- data/scripts/trainer_battle.inc | 8 +- data/scripts/trainer_hill.inc | 2 +- include/battle_setup.h | 22 +++- include/event_scripts.h | 2 + include/script_pokemon_util.h | 1 + src/battle_setup.c | 120 +++++++++++------- src/script_pokemon_util.c | 6 + src/trainer_see.c | 5 +- 12 files changed, 146 insertions(+), 82 deletions(-) diff --git a/asm/macros/battle_frontier/battle_tower.inc b/asm/macros/battle_frontier/battle_tower.inc index b965e2d84c7..8d76cbd64b0 100644 --- a/asm/macros/battle_frontier/battle_tower.inc +++ b/asm/macros/battle_frontier/battle_tower.inc @@ -115,14 +115,14 @@ .macro multi_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req special SavePlayerParty - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons - trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set second trainer mons + @trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons + @trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set second trainer mons 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, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons + @trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons multi_do MULTI_BATTLE_2_VS_1, \partnerId .endm @@ -145,14 +145,14 @@ .macro multi_fixed_2_vs_2 trainer1Id:req, trainer1LoseText:req, trainer2Id:req, trainer2LoseText:req, partnerId:req special SavePlayerParty - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons - trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set second trainer mons + @trainerbattle TRAINER_BATTLE_SET_TRAINER_A, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons + @trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set second trainer mons 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 + @trainerbattle TRAINER_BATTLE_SET_TRAINER_A, \trainer1Id, 0, NULL, \trainer1LoseText @ set first trainer mons multi_do_fixed MULTI_BATTLE_2_VS_1, \partnerId .endm diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 65cbcb87b6d..0c7eac3a9a8 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -685,14 +685,22 @@ NO_TRAINER = 0 @ Configures the arguments for a trainer battle, then jumps to the appropriate script in scripts/trainer_battle.inc - .macro trainerbattle type:req, localId:req, trainer_a:req, intro_text_a:req, lose_text_a:req, event_script_a:req, trainer_b:req, intro_text_b:req, lose_text_b:req, event_script_b:req, victory_text:req, cannot_battle:req + .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, playMusic:req, isRematch:req, isTrainerHill:req, isTrainerPyramid:req, isMulti:req .byte 0x5c - .byte \type @ battleMode - .2byte \localId @ objEventLocalId + .set trainerbattle_flags, 0 + .ifgt \isDouble; .set trainerbattle_flags, trainerbattle_flags | (1 << 0); .endif + .ifgt \playMusic; .set trainerbattle_flags, trainerbattle_flags | (1 << 1); .endif + .ifgt \isRematch; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif + .ifgt \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif + .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif + .ifgt \isMulti; .set trainerbattle_flags, trainerbattle_flags | (1 << 5); .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 @@ -705,11 +713,11 @@ @ 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, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, NULL + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, NULL + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, NULL + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE .endif .endm @@ -717,27 +725,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, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, 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, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, NULL + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE .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, NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE .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, NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_TRAINER, NULL, NULL, NULL, NULL, NULL + trainerbattle NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE .endm @ Starts a double battle with the player against two trainers diff --git a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index fb314bba349..da4bf270492 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, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL + @trainerbattle TRAINER_BATTLE_PYRAMID, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL pyramid_showhint waitmessage waitbuttonpress diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index 98979e997df..b0a20cec59a 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, LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, 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, LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_AxlePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Keegan:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_KeeganPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Danielle:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_DaniellePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Gerald:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_GeraldPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jace:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JacePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jeff:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JeffPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Eli:: - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, 0, 0, 0, 0, 0, 0 + trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_EliPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index 3df39bf8eac..216ce11dfba 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -146,6 +146,7 @@ EventScript_Lock:: EventScript_TrainerApproach2:: special DoTrainerApproach + waitstate return EventScript_RevealTrainer2:: @@ -185,7 +186,12 @@ EventScript_DoTrainerBattle2:: dotrainerbattle return +EventScript_DoRematchTrainerBattle:: + special BattleSetup_StartRematchBattle + waitstate + return + EventScript_EndTrainerBattle2:: gotobeatenscript releaseall - end \ No newline at end of file + end diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 78abfd6d4f5..0ea3d6b6480 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, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL + @trainerbattle TRAINER_BATTLE_HILL, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL trainerhill_postbattletext waitmessage waitbuttonpress diff --git a/include/battle_setup.h b/include/battle_setup.h index 21f0f786ef4..50745204c87 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -13,16 +13,27 @@ 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 TrainerBattleParameterUnion { struct PACKED Parameters { - u8 battleMode; - u16 objEventLocalId; + u8 isDoubleBattle:1; + u8 playMusic:1; + u8 isRematch:1; + u8 isTrainerHill:1; + u8 isTrainerPyramid:1; + u8 isMultiBattle:1; + u8 padding:2; + u8 objEventLocalIdA; u16 battleOpponentA; u8* introTextA; u8* defeatTextA; u8* battleScriptRetAddrA; + u8 objEventLocalIdB; u16 battleOpponentB; u8* introTextB; u8* defeatTextB; @@ -33,6 +44,13 @@ typedef union PACKED TrainerBattleParameterUnion u8 data[sizeof(struct Parameters)]; } TrainerBattleParameterU; +#define DebugPrintTrainerParams DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusic: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %d\nisMultiBattle: %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\nendscript: %x\n", \ + sTrainerBattleParameter.params.isDoubleBattle, sTrainerBattleParameter.params.playMusic, sTrainerBattleParameter.params.isRematch, sTrainerBattleParameter.params.isTrainerHill, sTrainerBattleParameter.params.isTrainerPyramid, sTrainerBattleParameter.params.isMultiBattle, sTrainerBattleParameter.params.padding, \ + sTrainerBattleParameter.params.objEventLocalIdA, sTrainerBattleParameter.params.battleOpponentA, sTrainerBattleParameter.params.introTextA, sTrainerBattleParameter.params.defeatTextA, sTrainerBattleParameter.params.battleScriptRetAddrA, \ + sTrainerBattleParameter.params.objEventLocalIdB, sTrainerBattleParameter.params.battleOpponentB, sTrainerBattleParameter.params.introTextB, sTrainerBattleParameter.params.defeatTextB, sTrainerBattleParameter.params.battleScriptRetAddrB, \ + sTrainerBattleParameter.params.victoryText, sTrainerBattleParameter.params.cannotBattleText, \ + sTrainerBattleEndScript) + typedef struct TrainerBattleScriptStack { const u8* stack[MAX_STACK_SIZE]; diff --git a/include/event_scripts.h b/include/event_scripts.h index 7789959578e..9efc3f27882 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -49,6 +49,8 @@ extern const u8 EventScript_ShowTrainerIntroMsg[]; extern const u8 EventScript_ShowTrainerIntroMsg2[]; extern const u8 EventScript_GotoPostBattleScript[]; extern const u8 EventScript_DoTrainerBattle2[]; +extern const u8 EventScript_DoRematchTrainerBattle[]; +extern const u8 EventScript_NotEnoughMonsForDoubleBattle[]; extern const u8 EventScript_EndTrainerBattle2[]; extern const u8 BerryTreeScript[]; diff --git a/include/script_pokemon_util.h b/include/script_pokemon_util.h index 6508295a2dc..aa50e3ba637 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/src/battle_setup.c b/src/battle_setup.c index 6b4e99a04b8..0663ac89c54 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -116,13 +116,6 @@ EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0; -#define DebugPrintTrainerParams DebugPrintfLevel(MGBA_LOG_DEBUG, "\nmode: %d\nlocalId: %d\ntrainerA: %d\nintroA: %x\ndefeatA: %x\neventA: %x\ntrainerB: %d\nintroB: %x\ndefeatB: %x\neventB: %x\nvictory: %x\nnotBattle:%x\nendscript: %x\n", \ - sTrainerBattleParameter.params.battleMode, sTrainerBattleParameter.params.objEventLocalId, \ - sTrainerBattleParameter.params.battleOpponentA, sTrainerBattleParameter.params.introTextA, sTrainerBattleParameter.params.defeatTextA, sTrainerBattleParameter.params.battleScriptRetAddrA, \ - sTrainerBattleParameter.params.battleOpponentB, sTrainerBattleParameter.params.introTextB, sTrainerBattleParameter.params.defeatTextB, sTrainerBattleParameter.params.battleScriptRetAddrB, \ - sTrainerBattleParameter.params.victoryText, sTrainerBattleParameter.params.cannotBattleText, \ - sTrainerBattleEndScript) - // The first transition is used if the enemy Pokémon are lower level than our Pokémon. // Otherwise, the second transition is used. static const u8 sBattleTransitionTable_Wild[][2] = @@ -1175,6 +1168,7 @@ void TrainerBattleLoadArgsTrainerA(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + 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; @@ -1185,6 +1179,7 @@ void TrainerBattleLoadArgsTrainerB(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + 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; @@ -1196,6 +1191,7 @@ void TrainerBattleLoadArgsSecondTrainer(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + 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; @@ -1212,10 +1208,10 @@ void TrainerBattleLoadArgs_2(const u8* data) void SetMapVarsToTrainer(void) { - if (TRAINER_BATTLE_PARAM.objEventLocalId != 0) + if (TRAINER_BATTLE_PARAM.objEventLocalIdA != 0) { - gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalId; - gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdA; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); } } @@ -1229,66 +1225,92 @@ do { \ DebugPrintfLevel(MGBA_LOG_DEBUG, "_______TrainerScriptFloor______"); \ } while(0) +#define PUSH(script) PtrStackPushU8(scrStack, script); -const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching) + +const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - /* - if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_SET_TRAINER_B) - InitTrainerBattleVariables(); - */ - + if (TRAINER_BATTLE_PARAM.playMusic) + { + PUSH(EventScript_PlayTrainerEncounterMusic); + } + + PUSH(EventScript_TrainerApproach2); + + if (TRAINER_BATTLE_PARAM.introTextA != NULL) + { + PUSH(EventScript_ShowTrainerIntroMsg2); + } + + if (TryPrepareSecondApproachingTrainer2()) { + PUSH(EventScript_PrepareSecondTrainerApproach); + PUSH(EventScript_PlayTrainerEncounterMusic); + PUSH(EventScript_TrainerApproach2); + PUSH(EventScript_ShowTrainerIntroMsg2); + } + PUSH(EventScript_DoTrainerBattle2); + PUSH(EventScript_EndTrainerBattle2); + return NULL; +} + +const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching) +{ DebugPrintTrainerParams; - if (isApproaching) { - PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); - PtrStackPushU8(scrStack, EventScript_TrainerApproach2); - PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); - if (TryPrepareSecondApproachingTrainer2()) { - PtrStackPushU8(scrStack, EventScript_PrepareSecondTrainerApproach); - PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); - PtrStackPushU8(scrStack, EventScript_TrainerApproach2); - PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); - } - PtrStackPushU8(scrStack, EventScript_DoTrainerBattle2); - PtrStackPushU8(scrStack, EventScript_EndTrainerBattle2); + if (isApproaching) + { + return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); + } + + + SetMapVarsToTrainer(); // TODO check which cases exactly need this and why + PUSH(EventScript_Lock); + PUSH(EventScript_RevealTrainer2); + + if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { + PUSH(EventScript_GotoPostBattleScript); return NULL; } - PtrStackPushU8(scrStack, EventScript_Lock); - PtrStackPushU8(scrStack, EventScript_RevealTrainer2); - - if (GetTrainerFlag()) + if (TRAINER_BATTLE_PARAM.isDoubleBattle && !HasEnoughMonsForDoubleBattle2()) { - PtrStackPushU8(scrStack, EventScript_GotoPostBattleScript); + PUSH(EventScript_NotEnoughMonsForDoubleBattle); return NULL; } - if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC - && TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC) + if (TRAINER_BATTLE_PARAM.isRematch) { - PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); + TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); + } + + if (TRAINER_BATTLE_PARAM.playMusic) + { + PUSH(EventScript_PlayTrainerEncounterMusic); } - PtrStackPushU8(scrStack, EventScript_SetTrainerFacingDirection); + PUSH(EventScript_SetTrainerFacingDirection); - if (TRAINER_BATTLE_PARAM.battleMode != TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT) + if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); + PUSH(EventScript_ShowTrainerIntroMsg2); } - if (gNoOfApproachingTrainers > 1) + if (TRAINER_BATTLE_PARAM.isRematch) { - PtrStackPushU8(scrStack, EventScript_PlayTrainerEncounterMusic); - PtrStackPushU8(scrStack, EventScript_TrainerApproach2); - PtrStackPushU8(scrStack, EventScript_ShowTrainerIntroMsg2); + PUSH(EventScript_DoRematchTrainerBattle); + } + else + { + PUSH(EventScript_DoTrainerBattle2); } - PtrStackPushU8(scrStack, EventScript_DoTrainerBattle2); - PtrStackPushU8(scrStack, EventScript_EndTrainerBattle2); + PUSH(EventScript_EndTrainerBattle2); + DebugPrintTrainerBattleStack; return NULL; - switch (TRAINER_BATTLE_PARAM.battleMode) + /* + switch (TRAINER_BATTLE_PARAM.battleFlags) { case TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT: return EventScript_DoNoIntroTrainerBattle; @@ -1368,6 +1390,7 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, SetMapVarsToTrainer(); return EventScript_TryDoNormalTrainerBattle; } + */ } void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript) @@ -1405,6 +1428,7 @@ bool32 GetTrainerFlagFromScriptPointer(const u8 *data) // For trainers who spot the player this is handled by PlayerFaceApproachingTrainer void SetTrainerFacingDirection(void) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "settrainerfacingdirection:\nselected: %d\nlast talked: %d\nfacing: %d", gSelectedObjectEvent, gSpecialVar_LastTalked, gSpecialVar_Facing); struct ObjectEvent *objectEvent = &gObjectEvents[gSelectedObjectEvent]; SetTrainerMovementType(objectEvent, GetTrainerFacingDirectionMovementType(objectEvent->facingDirection)); } @@ -1639,10 +1663,10 @@ 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 diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index dba872543ae..3b87273bfb0 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/trainer_see.c b/src/trainer_see.c index 98871c14b9d..903897bbcbb 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -473,9 +473,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) + TrainerBattleParameterU* temp = (TrainerBattleParameterU*)scriptPtr + 1; + if (temp->params.isDoubleBattle) { if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS) return 0; From 40938be3461406a3fd5ca3a002e79d7f2cf0d9bc Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 27 Jul 2024 01:12:59 +0200 Subject: [PATCH 12/39] small fix --- src/trainer_see.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trainer_see.c b/src/trainer_see.c index 903897bbcbb..b00afa96de6 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -473,7 +473,7 @@ static u8 CheckTrainer(u8 objectEventId) if (approachDistance != 0) { - TrainerBattleParameterU* temp = (TrainerBattleParameterU*)scriptPtr + 1; + TrainerBattleParameterU* temp = (TrainerBattleParameterU*)(scriptPtr + 1); if (temp->params.isDoubleBattle) { if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS) From 30c2b288c115f440fabf8eb44fdf480b87931e63 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 27 Jul 2024 01:16:57 +0200 Subject: [PATCH 13/39] first support for missing battle types. (very WIP) --- asm/macros/event.inc | 35 +++++---- data/scripts/trainer_battle.inc | 37 ++++++++++ include/battle_setup.h | 19 ++--- include/event_scripts.h | 8 +++ include/stack.h | 10 +++ src/battle_setup.c | 122 +++++++++++++++++++++++++++----- 6 files changed, 189 insertions(+), 42 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 0c7eac3a9a8..6e531896115 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -685,15 +685,16 @@ NO_TRAINER = 0 @ Configures the arguments for a trainer battle, then jumps to the appropriate script in scripts/trainer_battle.inc - .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, playMusic:req, isRematch:req, isTrainerHill:req, isTrainerPyramid:req, isMulti:req + .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, isTrainerHill:req, isTrainerPyramid:req, isMulti:req .byte 0x5c .set trainerbattle_flags, 0 .ifgt \isDouble; .set trainerbattle_flags, trainerbattle_flags | (1 << 0); .endif - .ifgt \playMusic; .set trainerbattle_flags, trainerbattle_flags | (1 << 1); .endif - .ifgt \isRematch; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif - .ifgt \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif - .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif - .ifgt \isMulti; .set trainerbattle_flags, trainerbattle_flags | (1 << 5); .endif + .ifgt \isRematch; .set trainerbattle_flags, trainerbattle_flags | (1 << 1); .endif + .ifgt \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif + .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif + .ifgt \isMulti; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif + .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 5); .endif + .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 6); .endif .byte trainerbattle_flags .byte \localIdA @ objEventLocalIdA .2byte \trainer_a @ battleOpponentA @@ -713,11 +714,11 @@ @ 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .else - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE .endif .endm @@ -725,27 +726,31 @@ @ 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .else - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE, 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE .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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + .endm + + .macro trainerbattle_2v2 trainer_a:req, intro_text_a:req, trainer_b:req, intro_text_b:req + trainerbattle NO_OBJ_ID, \trainer_a, \intro_text_a, NULL, NULL, NO_OBJ_ID, \trainer_b, \intro_text_b, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE .endm @ Starts a double battle with the player against two trainers diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index 216ce11dfba..fc26b4fa230 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -195,3 +195,40 @@ EventScript_EndTrainerBattle2:: gotobeatenscript releaseall end + +EventScript_SavePlayerParty:: + special SavePlayerParty + return + +EventScript_ChooseHalfPartyForBattle:: + fadescreen FADE_TO_BLACK + special ChooseHalfPartyForBattle + waitstate + return + +EventScript_LoadPlayerParty:: + special LoadPlayerParty + return + +EventScript_ReducePlayerPartyToSelectedMons:: + special ReducePlayerPartyToSelectedMons + return + +EventScript_SaveMonOrder:: + setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_DATA + setvar VAR_0x8005, FRONTIER_DATA_SELECTED_MON_ORDER + special CallFrontierUtilFunc @ saves the mon order, so the non-selected mons get restored afterwards + return + +EventScript_DoSpecialTrainerBattle:: + setvar VAR_0x8004, SPECIAL_BATTLE_MULTI + setvar VAR_0x8005, MULTI_BATTLE_2_VS_2 | MULTI_BATTLE_CHOOSE_MONS + setvar VAR_0x8006, PARTNER_STEVEN + special DoSpecialTrainerBattle + waitstate + return + +EventScript_SaveSelectedParty:: + setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY + special CallFrontierUtilFunc + return \ No newline at end of file diff --git a/include/battle_setup.h b/include/battle_setup.h index 50745204c87..03c019fd6a4 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -22,12 +22,13 @@ typedef union PACKED TrainerBattleParameterUnion struct PACKED Parameters { u8 isDoubleBattle:1; - u8 playMusic:1; u8 isRematch:1; u8 isTrainerHill:1; u8 isTrainerPyramid:1; u8 isMultiBattle:1; - u8 padding:2; + u8 playMusicA:1; + u8 playMusicB:1; + u8 padding:1; u8 objEventLocalIdA; u16 battleOpponentA; u8* introTextA; @@ -44,12 +45,11 @@ typedef union PACKED TrainerBattleParameterUnion u8 data[sizeof(struct Parameters)]; } TrainerBattleParameterU; -#define DebugPrintTrainerParams DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusic: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %d\nisMultiBattle: %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\nendscript: %x\n", \ - sTrainerBattleParameter.params.isDoubleBattle, sTrainerBattleParameter.params.playMusic, sTrainerBattleParameter.params.isRematch, sTrainerBattleParameter.params.isTrainerHill, sTrainerBattleParameter.params.isTrainerPyramid, sTrainerBattleParameter.params.isMultiBattle, sTrainerBattleParameter.params.padding, \ - sTrainerBattleParameter.params.objEventLocalIdA, sTrainerBattleParameter.params.battleOpponentA, sTrainerBattleParameter.params.introTextA, sTrainerBattleParameter.params.defeatTextA, sTrainerBattleParameter.params.battleScriptRetAddrA, \ - sTrainerBattleParameter.params.objEventLocalIdB, sTrainerBattleParameter.params.battleOpponentB, sTrainerBattleParameter.params.introTextB, sTrainerBattleParameter.params.defeatTextB, sTrainerBattleParameter.params.battleScriptRetAddrB, \ - sTrainerBattleParameter.params.victoryText, sTrainerBattleParameter.params.cannotBattleText, \ - sTrainerBattleEndScript) +#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %d\nisMultiBattle: %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.isTrainerHill, battleParameter->params.isTrainerPyramid, battleParameter->params.isMultiBattle, 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 { @@ -62,6 +62,7 @@ typedef struct TrainerBattleScriptStack extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; extern TrainerBattleParameterU sTrainerBattleParameter; +extern bool16 gHideCancelOptionOnPartySelect; extern u16 gTrainerBattleOpponent_A; extern u16 gTrainerBattleOpponent_B; extern u16 gPartnerTrainerId; @@ -83,7 +84,7 @@ u8 GetTrainerBattleTransition(void); u8 GetSpecialBattleTransition(s32 id); void ChooseStarter(void); void ResetTrainerOpponentIds(void); -void SetMapVarsToTrainer(void); +void SetMapVarsToTrainerA(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); diff --git a/include/event_scripts.h b/include/event_scripts.h index 9efc3f27882..101e63fb86d 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -53,6 +53,14 @@ extern const u8 EventScript_DoRematchTrainerBattle[]; extern const u8 EventScript_NotEnoughMonsForDoubleBattle[]; extern const u8 EventScript_EndTrainerBattle2[]; +extern const u8 EventScript_SavePlayerParty[]; +extern const u8 EventScript_ChooseHalfPartyForBattle[]; +extern const u8 EventScript_LoadPlayerParty[]; +extern const u8 EventScript_ReducePlayerPartyToSelectedMons[]; +extern const u8 EventScript_SaveMonOrder[]; +extern const u8 EventScript_DoSpecialTrainerBattle[]; +extern const u8 EventScript_SaveSelectedParty[]; + extern const u8 BerryTreeScript[]; extern const u8 gTVBravoTrainerText00[]; diff --git a/include/stack.h b/include/stack.h index b713706a826..87e5f59a0a9 100644 --- a/include/stack.h +++ b/include/stack.h @@ -9,6 +9,16 @@ typedef struct PtrStack 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); diff --git a/src/battle_setup.c b/src/battle_setup.c index 0663ac89c54..1feb739ce1f 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1168,6 +1168,7 @@ void TrainerBattleLoadArgsTrainerA(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)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; @@ -1179,6 +1180,7 @@ void TrainerBattleLoadArgsTrainerB(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)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; @@ -1191,6 +1193,7 @@ void TrainerBattleLoadArgsSecondTrainer(const u8* data) { TrainerBattleParameterU *temp = (TrainerBattleParameterU*)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; @@ -1203,10 +1206,10 @@ void TrainerBattleLoadArgs_2(const u8* data) InitTrainerBattleVariables(); memcpy(sTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameterU); - DebugPrintTrainerParams; + DebugPrintTrainerParams((&sTrainerBattleParameter)); } -void SetMapVarsToTrainer(void) +void SetMapVarsToTrainerA(void) { if (TRAINER_BATTLE_PARAM.objEventLocalIdA != 0) { @@ -1215,22 +1218,62 @@ void SetMapVarsToTrainer(void) } } -#define DebugPrintTrainerBattleStack \ -do { \ - s16 i; \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "_______TrainerScriptStack______"); \ - for (i = scrStack->stackPtr; i > -1; i--) { \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "%d: %x", i, scrStack->stack[i]); \ - } \ - DebugPrintfLevel(MGBA_LOG_DEBUG, "_______TrainerScriptFloor______"); \ -} while(0) +void SetMapVarsToTrainerB(void) +{ + if (TRAINER_BATTLE_PARAM.objEventLocalIdB != 0) + { + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdB; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdB, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + } +} #define PUSH(script) PtrStackPushU8(scrStack, script); +const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack *scrStack) +{ + if (TRAINER_BATTLE_PARAM.playMusicA) + { + PUSH(EventScript_PlayTrainerEncounterMusic); + } + + PUSH(EventScript_TrainerApproach2); + + if (TRAINER_BATTLE_PARAM.introTextA != NULL) + { + PUSH(EventScript_ShowTrainerIntroMsg2); + } + + PUSH(EventScript_SavePlayerParty); + PUSH(EventScript_ChooseHalfPartyForBattle); + PUSH(EventScript_LoadPlayerParty); + PUSH(EventScript_SavePlayerParty); + PUSH(EventScript_ReducePlayerPartyToSelectedMons); + PUSH(EventScript_SaveMonOrder); + PUSH(EventScript_DoSpecialTrainerBattle); + PUSH(EventScript_SaveSelectedParty); + PUSH(EventScript_LoadPlayerParty); + + return NULL; +} const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - if (TRAINER_BATTLE_PARAM.playMusic) + if (TRAINER_BATTLE_PARAM.isMultiBattle) + { + return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); + } + + if (TRAINER_BATTLE_PARAM.isTrainerPyramid) + { + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); + } + + if (TRAINER_BATTLE_PARAM.isTrainerHill) + { + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); + } + + if (TRAINER_BATTLE_PARAM.playMusicA) { PUSH(EventScript_PlayTrainerEncounterMusic); } @@ -1243,11 +1286,31 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P } if (TryPrepareSecondApproachingTrainer2()) { + SetMapVarsToTrainerB(); + if (TRAINER_BATTLE_PARAM.isTrainerPyramid) + { + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); + } + + if (TRAINER_BATTLE_PARAM.isTrainerHill) + { + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); + } + PUSH(EventScript_PrepareSecondTrainerApproach); - PUSH(EventScript_PlayTrainerEncounterMusic); + if (TRAINER_BATTLE_PARAM.playMusicB) + { + PUSH(EventScript_PlayTrainerEncounterMusic); + } + PUSH(EventScript_TrainerApproach2); - PUSH(EventScript_ShowTrainerIntroMsg2); + + if (TRAINER_BATTLE_PARAM.introTextB) + { + PUSH(EventScript_ShowTrainerIntroMsg2); + } } + PUSH(EventScript_DoTrainerBattle2); PUSH(EventScript_EndTrainerBattle2); return NULL; @@ -1255,15 +1318,19 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching) { - DebugPrintTrainerParams; + DebugPrintTrainerParams((&sTrainerBattleParameter)); if (isApproaching) { return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); } + if (TRAINER_BATTLE_PARAM.isMultiBattle) + { + return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); + } - SetMapVarsToTrainer(); // TODO check which cases exactly need this and why + SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why PUSH(EventScript_Lock); PUSH(EventScript_RevealTrainer2); @@ -1283,7 +1350,25 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); } - if (TRAINER_BATTLE_PARAM.playMusic) + if (TRAINER_BATTLE_PARAM.isTrainerPyramid) + { + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); + if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) + { + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); + } + } + + if (TRAINER_BATTLE_PARAM.isTrainerHill) + { + TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); + if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) + { + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); + } + } + + if (TRAINER_BATTLE_PARAM.playMusicA) { PUSH(EventScript_PlayTrainerEncounterMusic); } @@ -1306,7 +1391,8 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, PUSH(EventScript_EndTrainerBattle2); - DebugPrintTrainerBattleStack; + + DebugPrintStack(scrStack); return NULL; /* From e696d35da8bd17a8020302111bfe0b2f2d321d5c Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 10 Aug 2024 23:13:59 +0200 Subject: [PATCH 14/39] fix incorrect offset --- src/battle_setup.c | 2 +- src/trainer_see.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index 1feb739ce1f..7c6e376ff83 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1501,7 +1501,7 @@ void SetUpTwoTrainersBattle(void) LockPlayerFieldControls(); } -#define OFFSET_TRAINERID 4 +#define OFFSET_TRAINERID 3 bool32 GetTrainerFlagFromScriptPointer(const u8 *data) { u32 flag = TrainerBattleLoadArg16(data + OFFSET_TRAINERID); diff --git a/src/trainer_see.c b/src/trainer_see.c index b00afa96de6..933fe2911bd 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -417,7 +417,7 @@ bool8 CheckForTrainersWantingBattle(void) PtrStack trainerBattleScriptStack; PtrStackInit(&trainerBattleScriptStack); TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); - TrainerBattleLoadArgsSecondTrainer (gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); + TrainerBattleLoadArgsSecondTrainer(gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); ScriptContext_SetupScript(EventScript_StartTrainerApproach); From 5df72988b055b55829fbf4e8a2cacae8506bdb05 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sun, 11 Aug 2024 00:41:14 +0200 Subject: [PATCH 15/39] rename trainbattleparams var to show its global --- include/battle_setup.h | 4 ++-- src/battle_setup.c | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/battle_setup.h b/include/battle_setup.h index 03c019fd6a4..0311e56ff3b 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -57,11 +57,11 @@ typedef struct TrainerBattleScriptStack s8 stackPtr; } TrainerBattleScriptStack; -#define TRAINER_BATTLE_PARAM sTrainerBattleParameter.params +#define TRAINER_BATTLE_PARAM gTrainerBattleParameter.params extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; -extern TrainerBattleParameterU sTrainerBattleParameter; +extern TrainerBattleParameterU gTrainerBattleParameter; extern bool16 gHideCancelOptionOnPartySelect; extern u16 gTrainerBattleOpponent_A; extern u16 gTrainerBattleOpponent_B; diff --git a/src/battle_setup.c b/src/battle_setup.c index 7c6e376ff83..2f00806dff1 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -110,7 +110,7 @@ EWRAM_DATA static u8 *sTrainerCannotBattleSpeech = NULL; EWRAM_DATA static u8 *sTrainerABattleScriptRetAddr = NULL; EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL; -EWRAM_DATA TrainerBattleParameterU sTrainerBattleParameter = {0}; +EWRAM_DATA TrainerBattleParameterU gTrainerBattleParameter = {0}; EWRAM_DATA u16 gPartnerTrainerId = 0; EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; @@ -1106,7 +1106,7 @@ static void InitTrainerBattleVariables(void) sTrainerCannotBattleSpeech = NULL; sTrainerBattleEndScript = NULL; - memset(sTrainerBattleParameter.data, 0, sizeof(sTrainerBattleParameter)); + memset(gTrainerBattleParameter.data, 0, sizeof(gTrainerBattleParameter)); } static inline void SetU8(void *ptr, u8 value) @@ -1204,9 +1204,9 @@ void TrainerBattleLoadArgsSecondTrainer(const u8* data) void TrainerBattleLoadArgs_2(const u8* data) { InitTrainerBattleVariables(); - memcpy(sTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); + memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameterU); - DebugPrintTrainerParams((&sTrainerBattleParameter)); + DebugPrintTrainerParams((&gTrainerBattleParameter)); } void SetMapVarsToTrainerA(void) @@ -1318,7 +1318,7 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, bool32 isApproaching) { - DebugPrintTrainerParams((&sTrainerBattleParameter)); + DebugPrintTrainerParams((&gTrainerBattleParameter)); if (isApproaching) { @@ -1501,13 +1501,15 @@ void SetUpTwoTrainersBattle(void) LockPlayerFieldControls(); } +#define OPCODE_OFFSET 1 #define OFFSET_TRAINERID 3 bool32 GetTrainerFlagFromScriptPointer(const u8 *data) { - u32 flag = TrainerBattleLoadArg16(data + OFFSET_TRAINERID); - return FlagGet(TRAINER_FLAGS_START + flag); + TrainerBattleParameterU *temp = (TrainerBattleParameterU*)(data + OPCODE_OFFSET); + return FlagGet(TRAINER_FLAGS_START + temp->params.battleOpponentA); } #undef OFFSET_TRAINERID +#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 From 782f3cdacac46babd1d3686db1f43f57fdc5c8b9 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Mon, 23 Dec 2024 22:27:43 +0100 Subject: [PATCH 16/39] handle multiple approaching trainer --- src/trainer_see.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/trainer_see.c b/src/trainer_see.c index 933fe2911bd..821c27f38f3 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -392,6 +392,30 @@ bool8 CheckForTrainersWantingBattle(void) //DebugPrintfLevel(MGBA_LOG_DEBUG, "NoApprTrainers: %d", gNoOfApproachingTrainers); + if (gNoOfApproachingTrainers > 0) + { + ResetTrainerOpponentIds(); + + PtrStack trainerBattleScriptStack; + PtrStackInit(&trainerBattleScriptStack); + TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); + if (gNoOfApproachingTrainers > 1) + { + TrainerBattleLoadArgsSecondTrainer(gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); + gApproachingTrainerId = 0; + } + + BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); + ScriptContext_SetupScript(EventScript_StartTrainerApproach); + ScriptContext_PushFromStack(&trainerBattleScriptStack); + LockPlayerFieldControls(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gSelectedObjectEvent].localId; + gTrainerApproachedPlayer = TRUE; + return TRUE; + } + /* if (gNoOfApproachingTrainers == 1) { ResetTrainerOpponentIds(); @@ -431,6 +455,7 @@ bool8 CheckForTrainersWantingBattle(void) gTrainerApproachedPlayer = TRUE; return TRUE; } + */ else { gTrainerApproachedPlayer = FALSE; From d01af6316b643a372c9f9a584de98bc1dad1ec34 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Mon, 23 Dec 2024 22:36:32 +0100 Subject: [PATCH 17/39] rename eventscript snippets for better readability --- data/scripts/trainer_battle.inc | 22 ++++++++--------- include/event_scripts.h | 26 ++++++++++---------- src/battle_setup.c | 42 ++++++++++++++++----------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index fc26b4fa230..a0909dc25d9 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -138,18 +138,18 @@ Std_MsgboxAutoclose:: release return -EventScript_Lock:: +EventScript_LockSnippet:: lock faceplayer setflag FLAG_SAFE_FOLLOWER_MOVEMENT return -EventScript_TrainerApproach2:: +EventScript_TrainerApproachSnippet:: special DoTrainerApproach waitstate return -EventScript_RevealTrainer2:: +EventScript_RevealTrainerSnippet:: applymovement VAR_LAST_TALKED, Movement_RevealTrainer waitmovement 0 clearflag FLAG_SAFE_FOLLOWER_MOVEMENT @@ -160,38 +160,38 @@ EventScript_IsTrainerFlagSet:: goto_if_ne VAR_RESULT, FALSE, EventScript_NoNormalTrainerBattle return -EventScript_PlayTrainerEncounterMusic:: +EventScript_PlayTrainerEncounterMusicSnippet:: special PlayTrainerEncounterMusic return -EventScript_SetTrainerFacingDirection:: +EventScript_SetTrainerFacingDirectionSnippet:: special SetTrainerFacingDirection return -EventScript_ShowTrainerIntroMsg2:: +EventScript_ShowTrainerIntroMsgSnippet:: special ShowTrainerIntroSpeech waitmessage waitbuttonpress return -EventScript_PrepareSecondTrainerApproach:: +EventScript_PrepareSecondTrainerApproachSnippet:: special PrepareSecondApproachingTrainer return -EventScript_GotoPostBattleScript:: +EventScript_GotoPostBattleScriptSnippet:: gotopostbattlescript return -EventScript_DoTrainerBattle2:: +EventScript_DoTrainerBattleSnippet:: dotrainerbattle return -EventScript_DoRematchTrainerBattle:: +EventScript_DoRematchTrainerBattleSnippet:: special BattleSetup_StartRematchBattle waitstate return -EventScript_EndTrainerBattle2:: +EventScript_EndTrainerBattleSnippet:: gotobeatenscript releaseall end diff --git a/include/event_scripts.h b/include/event_scripts.h index 101e63fb86d..eb1c075ca56 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -37,21 +37,21 @@ extern const u8 EventScript_TryDoNormalTrainerBattle[]; extern const u8 EventScript_TryDoDoubleRematchBattle[]; extern const u8 EventScript_TryDoRematchBattle[]; -extern const u8 EventScript_Lock[]; -extern const u8 EventScript_TryDoNormalTrainerBattle2[]; -extern const u8 EventScript_RevealTrainer2[]; -extern const u8 EventScript_GetTrainerFlag[]; -extern const u8 EventScript_PlayTrainerEncounterMusic[]; -extern const u8 EventScript_SetTrainerFacingDirection[]; -extern const u8 EventScript_TrainerApproach2[]; -extern const u8 EventScript_PrepareSecondTrainerApproach[]; +extern const u8 EventScript_LockSnippet[]; +extern const u8 EventScript_TryDoNormalTrainerBattleSnippet[]; +extern const u8 EventScript_RevealTrainerSnippet[]; +extern const u8 EventScript_GetTrainerFlagSnippet[]; +extern const u8 EventScript_PlayTrainerEncounterMusicSnippet[]; +extern const u8 EventScript_SetTrainerFacingDirectionSnippet[]; +extern const u8 EventScript_TrainerApproachSnippet[]; +extern const u8 EventScript_PrepareSecondTrainerApproachSnippet[]; extern const u8 EventScript_ShowTrainerIntroMsg[]; -extern const u8 EventScript_ShowTrainerIntroMsg2[]; -extern const u8 EventScript_GotoPostBattleScript[]; -extern const u8 EventScript_DoTrainerBattle2[]; -extern const u8 EventScript_DoRematchTrainerBattle[]; +extern const u8 EventScript_ShowTrainerIntroMsgSnippet[]; +extern const u8 EventScript_GotoPostBattleScriptSnippet[]; +extern const u8 EventScript_DoTrainerBattleSnippet[]; +extern const u8 EventScript_DoRematchTrainerBattleSnippet[]; extern const u8 EventScript_NotEnoughMonsForDoubleBattle[]; -extern const u8 EventScript_EndTrainerBattle2[]; +extern const u8 EventScript_EndTrainerBattleSnippet[]; extern const u8 EventScript_SavePlayerParty[]; extern const u8 EventScript_ChooseHalfPartyForBattle[]; diff --git a/src/battle_setup.c b/src/battle_setup.c index 2f00806dff1..0d1a5fefa66 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1233,14 +1233,14 @@ const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack { if (TRAINER_BATTLE_PARAM.playMusicA) { - PUSH(EventScript_PlayTrainerEncounterMusic); + PUSH(EventScript_PlayTrainerEncounterMusicSnippet); } - PUSH(EventScript_TrainerApproach2); + PUSH(EventScript_TrainerApproachSnippet); if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - PUSH(EventScript_ShowTrainerIntroMsg2); + PUSH(EventScript_ShowTrainerIntroMsgSnippet); } PUSH(EventScript_SavePlayerParty); @@ -1275,14 +1275,14 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P if (TRAINER_BATTLE_PARAM.playMusicA) { - PUSH(EventScript_PlayTrainerEncounterMusic); + PUSH(EventScript_PlayTrainerEncounterMusicSnippet); } - PUSH(EventScript_TrainerApproach2); + PUSH(EventScript_TrainerApproachSnippet); if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - PUSH(EventScript_ShowTrainerIntroMsg2); + PUSH(EventScript_ShowTrainerIntroMsgSnippet); } if (TryPrepareSecondApproachingTrainer2()) { @@ -1297,22 +1297,22 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); } - PUSH(EventScript_PrepareSecondTrainerApproach); + PUSH(EventScript_PrepareSecondTrainerApproachSnippet); if (TRAINER_BATTLE_PARAM.playMusicB) { - PUSH(EventScript_PlayTrainerEncounterMusic); + PUSH(EventScript_PlayTrainerEncounterMusicSnippet); } - PUSH(EventScript_TrainerApproach2); + PUSH(EventScript_TrainerApproachSnippet); if (TRAINER_BATTLE_PARAM.introTextB) { - PUSH(EventScript_ShowTrainerIntroMsg2); + PUSH(EventScript_ShowTrainerIntroMsgSnippet); } } - PUSH(EventScript_DoTrainerBattle2); - PUSH(EventScript_EndTrainerBattle2); + PUSH(EventScript_DoTrainerBattleSnippet); + PUSH(EventScript_EndTrainerBattleSnippet); return NULL; } @@ -1331,11 +1331,11 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why - PUSH(EventScript_Lock); - PUSH(EventScript_RevealTrainer2); + PUSH(EventScript_LockSnippet); + PUSH(EventScript_RevealTrainerSnippet); if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { - PUSH(EventScript_GotoPostBattleScript); + PUSH(EventScript_GotoPostBattleScriptSnippet); return NULL; } @@ -1370,26 +1370,26 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, if (TRAINER_BATTLE_PARAM.playMusicA) { - PUSH(EventScript_PlayTrainerEncounterMusic); + PUSH(EventScript_PlayTrainerEncounterMusicSnippet); } - PUSH(EventScript_SetTrainerFacingDirection); + PUSH(EventScript_SetTrainerFacingDirectionSnippet); if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - PUSH(EventScript_ShowTrainerIntroMsg2); + PUSH(EventScript_ShowTrainerIntroMsgSnippet); } if (TRAINER_BATTLE_PARAM.isRematch) { - PUSH(EventScript_DoRematchTrainerBattle); + PUSH(EventScript_DoRematchTrainerBattleSnippet); } else { - PUSH(EventScript_DoTrainerBattle2); + PUSH(EventScript_DoTrainerBattleSnippet); } - PUSH(EventScript_EndTrainerBattle2); + PUSH(EventScript_EndTrainerBattleSnippet); DebugPrintStack(scrStack); From 0d447f17585757ffca1ac2034a7c194e5fb98c19 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Wed, 25 Dec 2024 22:57:14 +0100 Subject: [PATCH 18/39] integrate multi battle support in regular battles. (wip) --- asm/macros/event.inc | 33 ++--- data/maps/LavaridgeTown_Gym_1F/scripts.inc | 20 +-- data/maps/Route102/scripts.inc | 5 +- data/scripts/trainer_battle.inc | 16 ++- data/specials.inc | 2 + include/battle_setup.h | 12 +- include/battle_tower.h | 2 + include/constants/battle.h | 2 +- include/constants/battle_partner.h | 1 + include/event_scripts.h | 2 + src/battle_setup.c | 87 ++++++++++--- src/battle_tower.c | 137 ++++++++++++++------- src/data/battle_partners.h | 80 ++++++++++++ src/data/battle_partners.party | 37 ++++++ src/party_menu.c | 16 +++ 15 files changed, 354 insertions(+), 98 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 6e531896115..f8ba194470b 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -681,20 +681,20 @@ .endm NULL = 0 - NO_OBJ_ID = 0 - NO_TRAINER = 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 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, isTrainerHill:req, isTrainerPyramid:req, isMulti:req + .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, isTrainerHill:req, isTrainerPyramid:req, battlePartner:req, mutliChooseMon:req, multiChooseCancel:req .byte 0x5c .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 \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif - .ifgt \isMulti; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif - .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 5); .endif - .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 6); .endif + .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif + .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 5); .endif + .ifgt \mutliChooseMon; .set trainerbattle_flags, trainerbattle_flags | (1 << 6); .endif + .ifgt \multiChooseCancel; .set trainerbattle_flags, trainerbattle_flags | (1 << 7); .endif .byte trainerbattle_flags .byte \localIdA @ objEventLocalIdA .2byte \trainer_a @ battleOpponentA @@ -708,17 +708,18 @@ .4byte \event_script_b @ retAddrB .4byte \victory_text @ victoryText .4byte \cannot_battle @ cannotBattle + .4byte \battlePartner @ battlePartner .endm @ 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .elseif \music == TRUE - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .else - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .endif .endm @@ -726,31 +727,31 @@ @ 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .elseif \music == TRUE - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .else - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE, PARTNER_NONE, 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE + 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + trainerbattle OBJ_ID_NONE, \trainer, NULL, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE .endm .macro trainerbattle_2v2 trainer_a:req, intro_text_a:req, trainer_b:req, intro_text_b:req - trainerbattle NO_OBJ_ID, \trainer_a, \intro_text_a, NULL, NULL, NO_OBJ_ID, \trainer_b, \intro_text_b, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE + trainerbattle OBJ_ID_NONE, \trainer_a, \intro_text_a, NULL, NULL, OBJ_ID_NONE, \trainer_b, \intro_text_b, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, PARTNER_NONE .endm @ Starts a double battle with the player against two trainers diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index b0a20cec59a..e624c5e548f 100644 --- a/data/maps/LavaridgeTown_Gym_1F/scripts.inc +++ b/data/maps/LavaridgeTown_Gym_1F/scripts.inc @@ -49,7 +49,7 @@ LavaridgeTown_Gym_1F_EventScript_EndCheckBuryTrainers:: return LavaridgeTown_Gym_1F_EventScript_Flannery:: - trainerbattle_single TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryIntro, LavaridgeTown_Gym_1F_Text_FlanneryDefeat, LavaridgeTown_Gym_1F_EventScript_FlanneryDefeated, NO_MUSIC + @trainerbattle_single TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryIntro, LavaridgeTown_Gym_1F_Text_FlanneryDefeat, LavaridgeTown_Gym_1F_EventScript_FlanneryDefeated, NO_MUSIC specialvar VAR_RESULT, ShouldTryRematchBattle goto_if_eq VAR_RESULT, TRUE, LavaridgeTown_Gym_1F_EventScript_FlanneryRematch goto_if_unset FLAG_RECEIVED_TM_OVERHEAT, LavaridgeTown_Gym_1F_EventScript_GiveOverheat2 @@ -99,12 +99,12 @@ LavaridgeTown_Gym_1F_EventScript_GiveOverheat:: return LavaridgeTown_Gym_1F_EventScript_FlanneryRematch:: - trainerbattle_rematch_double TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryPreRematch, LavaridgeTown_Gym_1F_Text_FlanneryRematchDefeat, LavaridgeTown_Gym_1F_Text_FlanneryRematchNeedTwoMons + @trainerbattle_rematch_double TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryPreRematch, LavaridgeTown_Gym_1F_Text_FlanneryRematchDefeat, LavaridgeTown_Gym_1F_Text_FlanneryRematchNeedTwoMons msgbox LavaridgeTown_Gym_1F_Text_FlanneryPostRematch, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Cole:: - trainerbattle LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, 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 LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_AxlePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Keegan:: - trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_KeeganPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Danielle:: - trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_DaniellePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Gerald:: - trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_GeraldPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jace:: - trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JacePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jeff:: - trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JeffPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Eli:: - trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + @trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_EliPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index 4f782fc7c2c..99ed0b8f3be 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -64,13 +64,14 @@ Route102_EventScript_Rick:: end Route102_EventScript_Tiana:: - trainerbattle_single TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated + @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, isTrainerHill:req, isTrainerPyramid:req, mutliChooseMon:req, battlePartner:req + trainerbattle OBJ_ID_NONE, TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, PARTNER_STEVEN, TRUE, TRUE Route102_EventScript_TianaMsg:: msgbox Route102_Text_TianaPostBattle, MSGBOX_AUTOCLOSE end Route102_EventScript_Allen:: - trainerbattle_single TRAINER_ALLEN, Route102_Text_AllenIntro, Route102_Text_AllenDefeated + trainerbattle OBJ_ID_NONE, TRAINER_ALLEN, Route102_Text_AllenIntro, Route102_Text_AllenDefeated, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, PARTNER_PHTEVEN, FALSE, FALSE msgbox Route102_Text_AllenPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index a0909dc25d9..928478e6161 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -221,14 +221,22 @@ EventScript_SaveMonOrder:: return EventScript_DoSpecialTrainerBattle:: - setvar VAR_0x8004, SPECIAL_BATTLE_MULTI - setvar VAR_0x8005, MULTI_BATTLE_2_VS_2 | MULTI_BATTLE_CHOOSE_MONS - setvar VAR_0x8006, PARTNER_STEVEN special DoSpecialTrainerBattle waitstate return +EventScript_DoMultiTrainerBattle:: + special DoMultiTrainerBattle + waitstate + return + +EventScript_DoFacilityTrainerBattle:: + special DoFacilityTrainerBattle + waitstate + return + EventScript_SaveSelectedParty:: setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY special CallFrontierUtilFunc - return \ No newline at end of file + return + diff --git a/data/specials.inc b/data/specials.inc index f12f4e20e50..78a0b3002b0 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -555,3 +555,5 @@ gSpecials:: def_special Script_GetChosenMonDefensiveEVs def_special Script_GetChosenMonOffensiveIVs def_special Script_GetChosenMonDefensiveIVs + def_special DoMultiTrainerBattle + def_special DoFacilityTrainerBattle diff --git a/include/battle_setup.h b/include/battle_setup.h index 0311e56ff3b..d870a346627 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -25,10 +25,10 @@ typedef union PACKED TrainerBattleParameterUnion u8 isRematch:1; u8 isTrainerHill:1; u8 isTrainerPyramid:1; - u8 isMultiBattle:1; u8 playMusicA:1; u8 playMusicB:1; - u8 padding:1; + u8 multiChooseMons:1; + u8 multiChooseCancel:1; u8 objEventLocalIdA; u16 battleOpponentA; u8* introTextA; @@ -41,15 +41,16 @@ typedef union PACKED TrainerBattleParameterUnion u8* battleScriptRetAddrB; u8* victoryText; u8* cannotBattleText; + u16 battlePartner; } params; u8 data[sizeof(struct Parameters)]; } TrainerBattleParameterU; -#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %d\nisMultiBattle: %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.isTrainerHill, battleParameter->params.isTrainerPyramid, battleParameter->params.isMultiBattle, battleParameter->params.padding, \ +#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %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\npartner: %d\nchoose mons: %d\nallow cancel: %d\n", \ + battleParameter->params.isDoubleBattle, battleParameter->params.playMusicA, battleParameter->params.playMusicB, battleParameter->params.isRematch, battleParameter->params.isTrainerHill, battleParameter->params.isTrainerPyramid, \ 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) + battleParameter->params.victoryText, battleParameter->params.cannotBattleText, battleParameter->params.battlePartner, battleParameter->params.multiChooseMons, battleParameter->params.multiChooseCancel) typedef struct TrainerBattleScriptStack { @@ -126,5 +127,6 @@ 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); +void CB2_EndTrainerBattle(void); #endif // GUARD_BATTLE_SETUP_H diff --git a/include/battle_tower.h b/include/battle_tower.h index 074fccf3a5f..26fab390732 100644 --- a/include/battle_tower.h +++ b/include/battle_tower.h @@ -78,4 +78,6 @@ bool32 ValidateBattleTowerRecord(u8 recordId); // unused void TrySetLinkBattleTowerEnemyPartyLevel(void); void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst); +void DoMultiTrainerBattle(void); +void DoFacilityTrainerBattle(void); #endif //GUARD_BATTLE_TOWER_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 91289f718eb..a2be627be47 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 && TRAINER_BATTLE_PARAM.battleOpponentB == 0xFFFF)) +#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.battleOpponentB == 0)) #define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER) diff --git a/include/constants/battle_partner.h b/include/constants/battle_partner.h index 5622349a888..402f2d0500c 100644 --- a/include/constants/battle_partner.h +++ b/include/constants/battle_partner.h @@ -4,5 +4,6 @@ #define PARTNER_NONE 0 #define PARTNER_STEVEN 1 +#define PARTNER_PHTEVEN 2 #endif // GUARD_CONSTANTS_BATTLE_PARTNERS_H diff --git a/include/event_scripts.h b/include/event_scripts.h index eb1c075ca56..9293dea9638 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -59,6 +59,8 @@ extern const u8 EventScript_LoadPlayerParty[]; extern const u8 EventScript_ReducePlayerPartyToSelectedMons[]; extern const u8 EventScript_SaveMonOrder[]; extern const u8 EventScript_DoSpecialTrainerBattle[]; +extern const u8 EventScript_DoMultiTrainerBattle[]; +extern const u8 EventScript_DoFacilityTrainerBattle[]; extern const u8 EventScript_SaveSelectedParty[]; extern const u8 BerryTreeScript[]; diff --git a/src/battle_setup.c b/src/battle_setup.c index 0d1a5fefa66..e4c0ea03948 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -42,6 +42,7 @@ #include "item.h" #include "constants/battle_frontier.h" #include "constants/battle_setup.h" +#include "constants/battle_tower.h" #include "constants/game_stat.h" #include "constants/items.h" #include "constants/songs.h" @@ -86,7 +87,6 @@ static void CB2_StartFirstBattle(void); static void CB2_EndFirstBattle(void); static void SaveChangesToPlayerParty(void); static void HandleBattleVariantEndParty(void); -static void CB2_EndTrainerBattle(void); static bool32 IsPlayerDefeated(u32 battleOutcome); #if FREE_MATCH_CALL == FALSE static u16 GetRematchTrainerId(u16 trainerId); @@ -1229,27 +1229,80 @@ void SetMapVarsToTrainerB(void) #define PUSH(script) PtrStackPushU8(scrStack, script); -const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack *scrStack) +#include "party_menu.h" + +const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack *scrStack, bool16 isApproaching) { + + if (!isApproaching) + { + SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why + PUSH(EventScript_LockSnippet); + PUSH(EventScript_RevealTrainerSnippet); + + if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { + PUSH(EventScript_GotoPostBattleScriptSnippet); + return NULL; + } + + } if (TRAINER_BATTLE_PARAM.playMusicA) { PUSH(EventScript_PlayTrainerEncounterMusicSnippet); } - PUSH(EventScript_TrainerApproachSnippet); + if (isApproaching) + { + PUSH(EventScript_TrainerApproachSnippet); - if (TRAINER_BATTLE_PARAM.introTextA != NULL) + if (TRAINER_BATTLE_PARAM.introTextA != NULL) + { + PUSH(EventScript_ShowTrainerIntroMsgSnippet); + } + + if (TryPrepareSecondApproachingTrainer2()) { + SetMapVarsToTrainerB(); + if (TRAINER_BATTLE_PARAM.isTrainerPyramid) + { + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); + } + + if (TRAINER_BATTLE_PARAM.isTrainerHill) + { + TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); + } + + PUSH(EventScript_PrepareSecondTrainerApproachSnippet); + if (TRAINER_BATTLE_PARAM.playMusicB) + { + PUSH(EventScript_PlayTrainerEncounterMusicSnippet); + } + + PUSH(EventScript_TrainerApproachSnippet); + + if (TRAINER_BATTLE_PARAM.introTextB) + { + PUSH(EventScript_ShowTrainerIntroMsgSnippet); + } + } + } + else { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); + if (TRAINER_BATTLE_PARAM.introTextA != NULL) + { + PUSH(EventScript_ShowTrainerIntroMsgSnippet); + } } PUSH(EventScript_SavePlayerParty); - PUSH(EventScript_ChooseHalfPartyForBattle); - PUSH(EventScript_LoadPlayerParty); - PUSH(EventScript_SavePlayerParty); + + if (TRAINER_BATTLE_PARAM.multiChooseMons) + { + PUSH(EventScript_ChooseHalfPartyForBattle); + } PUSH(EventScript_ReducePlayerPartyToSelectedMons); PUSH(EventScript_SaveMonOrder); - PUSH(EventScript_DoSpecialTrainerBattle); + PUSH(EventScript_DoMultiTrainerBattle); PUSH(EventScript_SaveSelectedParty); PUSH(EventScript_LoadPlayerParty); @@ -1258,9 +1311,9 @@ const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - if (TRAINER_BATTLE_PARAM.isMultiBattle) + if (TRAINER_BATTLE_PARAM.battlePartner != PARTNER_NONE) { - return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); + return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack, TRUE); } if (TRAINER_BATTLE_PARAM.isTrainerPyramid) @@ -1324,9 +1377,9 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, { return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); } - if (TRAINER_BATTLE_PARAM.isMultiBattle) + if (TRAINER_BATTLE_PARAM.battlePartner != PARTNER_NONE) { - return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); + return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack, FALSE); } @@ -1384,7 +1437,7 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, { PUSH(EventScript_DoRematchTrainerBattleSnippet); } - else + else { PUSH(EventScript_DoTrainerBattleSnippet); } @@ -1541,6 +1594,8 @@ static void SetBattledTrainersFlags(void) if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) FlagSet(GetTrainerBFlag()); FlagSet(GetTrainerAFlag()); + + DebugPrintfLevel(MGBA_LOG_DEBUG, "a: %d b: %d", GetTrainerAFlag(), GetTrainerBFlag()); } static void UNUSED SetBattledTrainerFlag(void) @@ -1654,8 +1709,9 @@ static void HandleBattleVariantEndParty(void) FlagClear(B_FLAG_SKY_BATTLE); } -static void CB2_EndTrainerBattle(void) +void CB2_EndTrainerBattle(void) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "here %d, %d", IsPlayerDefeated(gBattleOutcome), gBattleOutcome); HandleBattleVariantEndParty(); if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) @@ -1676,6 +1732,7 @@ static void CB2_EndTrainerBattle(void) DowngradeBadPoison(); if (!InBattlePyramid() && !InTrainerHillChallenge()) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "here2"); RegisterTrainerInMatchCall(); SetBattledTrainersFlags(); } diff --git a/src/battle_tower.c b/src/battle_tower.c index fed05b0e4d2..6d59989ff4c 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -1934,6 +1934,29 @@ static void GetOpponentIntroSpeech(void) else BufferApprenticeChallengeText(trainerId - TRAINER_RECORD_MIXING_APPRENTICE); } +static void HandleMultiTrainerBattleEnd(void) +{ + s32 i; + + RecordedBattle_SaveBattleOutcome(); + + if (!TRAINER_BATTLE_PARAM.multiChooseMons) + { + for (i = 0; i < 3; i++) // TODO magic number + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES)) + gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i]; + } + } + + SetMainCallback2(CB2_EndTrainerBattle); +} + +static void HandleFacilityTrainerBattleEnd(void) +{ + // TODO move facility battles to here + return; +} static void HandleSpecialTrainerBattleEnd(void) { @@ -1971,19 +1994,32 @@ static void HandleSpecialTrainerBattleEnd(void) case SPECIAL_BATTLE_EREADER: CopyEReaderTrainerFarewellMessage(); break; - case SPECIAL_BATTLE_MULTI: - for (i = 0; i < 3; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES)) - gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i]; - } - break; } SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); } -static void Task_StartBattleAfterTransition(u8 taskId) +static void Task_StartMultiBattleAfterTransition(u8 taskId) +{ + if (IsBattleTransitionDone() == TRUE) + { + gMain.savedCallback = HandleMultiTrainerBattleEnd; + SetMainCallback2(CB2_InitBattle); + DestroyTask(taskId); + } +} + +static void Task_StartFacilityBattleAfterTransition(u8 taskId) +{ + if (IsBattleTransitionDone() == TRUE) + { + gMain.savedCallback = HandleSpecialTrainerBattleEnd; + SetMainCallback2(CB2_InitBattle); + DestroyTask(taskId); + } +} + +static void Task_StartSpecialBattleAfterTransition(u8 taskId) { if (IsBattleTransitionDone() == TRUE) { @@ -1993,6 +2029,44 @@ static void Task_StartBattleAfterTransition(u8 taskId) } } +void DoMultiTrainerBattle(void) +{ + gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; + if (TRAINER_BATTLE_PARAM.battleOpponentA != TRAINER_NONE) // is not against wild pokemon + { + gBattleTypeFlags |= BATTLE_TYPE_TRAINER; + } + if (TRAINER_BATTLE_PARAM.battleOpponentB != TRAINER_NONE) // is 2 vs 2 not 2 vs 1 + { + gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS; + } + + DebugPrintfLevel(MGBA_LOG_DEBUG, "flags: %x", gBattleTypeFlags); + gPartnerTrainerId = TRAINER_PARTNER(TRAINER_BATTLE_PARAM.battlePartner); // implement override for partner id + + FillPartnerParty(gPartnerTrainerId); + CreateTask(Task_StartMultiBattleAfterTransition, 1); + + /* + might be redundant with the other music + if (TRAINER_BATTLE_PARAM.playMusicA) + { + PlayMapChosenOrBattleBGM(0); + } + */ + + if (TRAINER_BATTLE_PARAM.battleOpponentA != TRAINER_NONE) + BattleTransition_StartOnField(GetTrainerBattleTransition()); + else + BattleTransition_StartOnField(GetWildBattleTransition()); +} + +void DoFacilityTrainerBattle(void) +{ + // TODO move facility stuff here + return; +} + void DoSpecialTrainerBattle(void) { s32 i; @@ -2022,7 +2096,7 @@ void DoSpecialTrainerBattle(void) FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE); break; } - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_TOWER)); break; @@ -2032,7 +2106,7 @@ void DoSpecialTrainerBattle(void) u16 itemBefore = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); SetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM, &itemBefore); } - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_SECRET_BASE)); break; @@ -2043,7 +2117,7 @@ void DoSpecialTrainerBattle(void) CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i]); gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_EREADER_TRAINER; TRAINER_BATTLE_PARAM.battleOpponentA = 0; - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_E_READER)); #endif //FREE_BATTLE_TOWER_E_READER @@ -2054,7 +2128,7 @@ void DoSpecialTrainerBattle(void) gBattleTypeFlags |= BATTLE_TYPE_DOUBLE; if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); CreateTask_PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_DOME)); break; @@ -2066,7 +2140,7 @@ void DoSpecialTrainerBattle(void) FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); else FillTentTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PALACE)); break; @@ -2076,7 +2150,7 @@ void DoSpecialTrainerBattle(void) FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); else FillTentTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_ARENA)); break; @@ -2085,58 +2159,31 @@ void DoSpecialTrainerBattle(void) if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES) gBattleTypeFlags |= BATTLE_TYPE_DOUBLE; FillFactoryTrainerParty(); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_FACTORY)); break; case SPECIAL_BATTLE_PIKE_SINGLE: gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER; FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PIKE)); break; case SPECIAL_BATTLE_PYRAMID: gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID; FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID)); break; case SPECIAL_BATTLE_PIKE_DOUBLE: gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS; FillFrontierTrainersParties(1); - CreateTask(Task_StartBattleAfterTransition, 1); + CreateTask(Task_StartSpecialBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PIKE)); break; - case SPECIAL_BATTLE_MULTI: - if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD) // Player + AI against wild mon - { - gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; - } - else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer - { - 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 - { - gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; - } - - gPartnerTrainerId = VarGet(gSpecialVar_0x8006) + TRAINER_PARTNER(PARTNER_NONE); - FillPartnerParty(gPartnerTrainerId); - CreateTask(Task_StartBattleAfterTransition, 1); - PlayMapChosenOrBattleBGM(0); - if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD) - BattleTransition_StartOnField(GetWildBattleTransition()); - else - BattleTransition_StartOnField(GetTrainerBattleTransition()); - - if (gSpecialVar_0x8005 & MULTI_BATTLE_CHOOSE_MONS) // Skip mons restoring(done in the script) - gBattleScripting.specialTrainerBattleType = 0xFF; - break; } } diff --git a/src/data/battle_partners.h b/src/data/battle_partners.h index ae0b753cb3b..d6b01f42291 100644 --- a/src/data/battle_partners.h +++ b/src/data/battle_partners.h @@ -103,3 +103,83 @@ }, }, }, +#line 45 + [PARTNER_PHTEVEN] = + { +#line 46 + .trainerName = _("PHTEVEN"), +#line 47 + .trainerClass = TRAINER_CLASS_RIVAL, +#line 48 + .trainerPic = TRAINER_BACK_PIC_STEVEN, + .encounterMusic_gender = +#line 50 + TRAINER_ENCOUNTER_MUSIC_MALE, + .partySize = 3, + .party = (const struct TrainerMon[]) + { + { +#line 52 + .species = SPECIES_SKARMORY, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 56 + .ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252), +#line 55 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 54 + .lvl = 43, +#line 53 + .nature = NATURE_IMPISH, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 57 + MOVE_TOXIC, + MOVE_AERIAL_ACE, + MOVE_PROTECT, + MOVE_STEEL_WING, + }, + }, + { +#line 62 + .species = SPECIES_METANG, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 66 + .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), +#line 65 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 64 + .lvl = 42, +#line 63 + .nature = NATURE_BRAVE, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 67 + MOVE_LIGHT_SCREEN, + MOVE_PSYCHIC, + MOVE_REFLECT, + MOVE_METAL_CLAW, + }, + }, + { +#line 72 + .species = SPECIES_AGGRON, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 76 + .ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6), +#line 75 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 74 + .lvl = 44, +#line 73 + .nature = NATURE_ADAMANT, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 77 + MOVE_THUNDER, + MOVE_PROTECT, + MOVE_SOLAR_BEAM, + MOVE_DRAGON_CLAW, + }, + }, + }, + }, diff --git a/src/data/battle_partners.party b/src/data/battle_partners.party index e1ecfe35faa..15758e9ff9c 100644 --- a/src/data/battle_partners.party +++ b/src/data/battle_partners.party @@ -41,3 +41,40 @@ EVs: 252 Atk / 252 SpA / 6 SpD - Protect - Solar Beam - Dragon Claw + +=== PARTNER_PHTEVEN === +Name: PHTEVEN +Class: Rival +Pic: Steven +Gender: Male +Music: Male + +Skarmory +Impish Nature +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 HP / 6 SpA / 252 SpD +- Toxic +- Aerial Ace +- Protect +- Steel Wing + +Metang +Brave Nature +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 Atk / 252 Def / 6 SpA +- Light Screen +- Psychic +- Reflect +- Metal Claw + +Aggron +Adamant Nature +Level: 44 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 Atk / 252 SpA / 6 SpD +- Thunder +- Protect +- Solar Beam +- Dragon Claw \ No newline at end of file diff --git a/src/party_menu.c b/src/party_menu.c index c46c74393f7..76a8395f85a 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -506,6 +506,7 @@ static bool8 SetUpFieldMove_Dive(void); void TryItemHoldFormChange(struct Pokemon *mon); static void ShowMoveSelectWindow(u8 slot); static void Task_HandleWhichMoveInput(u8 taskId); +static void UpdateSelectedOrderFromParty(void); // static const data #include "data/party_menu.h" @@ -1381,7 +1382,13 @@ static void Task_ClosePartyMenuAndSetCB2(u8 taskId) if (!gPaletteFade.active) { if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE) + { UpdatePartyToFieldOrder(); + } + else if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF) + { + UpdateSelectedOrderFromParty(); + } if (sPartyMenuInternal->exitCallback != NULL) SetMainCallback2(sPartyMenuInternal->exitCallback); @@ -7434,6 +7441,15 @@ static void UpdatePartyToFieldOrder(void) Free(partyBuffer); } +static void UpdateSelectedOrderFromParty(void) +{ + u8 i; + for (i = 0; i < MAX_FRONTIER_PARTY_SIZE; i++) + { + gSelectedOrderFromParty[i] = i + 1; + } +} + static void UNUSED SwitchAliveMonIntoLeadSlot(void) { u8 i; From 0c3f30283defc0fac98dffa09dcf3c0b7c0e150c Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Wed, 25 Dec 2024 23:03:08 +0100 Subject: [PATCH 19/39] fix no selection multi battles --- src/battle_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index e4c0ea03948..599dab9448e 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1299,8 +1299,8 @@ const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack if (TRAINER_BATTLE_PARAM.multiChooseMons) { PUSH(EventScript_ChooseHalfPartyForBattle); + PUSH(EventScript_ReducePlayerPartyToSelectedMons); } - PUSH(EventScript_ReducePlayerPartyToSelectedMons); PUSH(EventScript_SaveMonOrder); PUSH(EventScript_DoMultiTrainerBattle); PUSH(EventScript_SaveSelectedParty); From 54acc565abe168f40b984a3f5882a85fa305640a Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Thu, 26 Dec 2024 12:59:52 +0100 Subject: [PATCH 20/39] wild multi battles --- asm/macros/event.inc | 9 ++++++++ data/specials.inc | 1 + include/battle_setup.h | 2 ++ include/global.h | 1 + src/battle_setup.c | 10 +++++++-- src/battle_tower.c | 49 +++++++++++++++++++++++++++++++----------- src/scrcmd.c | 12 +++++++++++ 7 files changed, 69 insertions(+), 15 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index f8ba194470b..d270e23587a 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2279,3 +2279,12 @@ .macro setwilddoubleflag callnative ScriptSetDoubleBattleFlag .endm + + .macro setbattlepartner partnerId:req + callnative SetBattlePartner + .2byte \partnerId + .endm + + .macro clearbattlepartner + callnative ClearBattlePartner + .endm \ No newline at end of file diff --git a/data/specials.inc b/data/specials.inc index 78a0b3002b0..8085445b599 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -557,3 +557,4 @@ gSpecials:: def_special Script_GetChosenMonDefensiveIVs def_special DoMultiTrainerBattle def_special DoFacilityTrainerBattle + def_special DoMultiWildBattle diff --git a/include/battle_setup.h b/include/battle_setup.h index d870a346627..47d7ddcc39f 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -128,5 +128,7 @@ s32 TrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId) s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId); u16 GetRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId); void CB2_EndTrainerBattle(void); +void CB2_EndScriptedWildBattle(void); +u16 GetBattlePartner(u16 partnerId); #endif // GUARD_BATTLE_SETUP_H diff --git a/include/global.h b/include/global.h index d872d9d303a..1c1856a337e 100644 --- a/include/global.h +++ b/include/global.h @@ -1084,6 +1084,7 @@ struct SaveBlock1 /*0x3???*/ struct TrainerHillSave trainerHill; #endif //FREE_TRAINER_HILL /*0x3???*/ struct WaldaPhrase waldaPhrase; + /*0x3???*/ u16 battlePartnerOverride; // sizeof: 0x3??? }; diff --git a/src/battle_setup.c b/src/battle_setup.c index 599dab9448e..fe708751680 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -79,7 +79,6 @@ static void DoBattlePikeWildBattle(void); static void DoSafariBattle(void); static void DoStandardWildBattle(bool32 isDouble); static void CB2_EndWildBattle(void); -static void CB2_EndScriptedWildBattle(void); static void TryUpdateGymLeaderRematchFromWild(void); static void TryUpdateGymLeaderRematchFromTrainer(void); static void CB2_GiveStarter(void); @@ -729,7 +728,7 @@ static void CB2_EndWildBattle(void) } } -static void CB2_EndScriptedWildBattle(void) +void CB2_EndScriptedWildBattle(void) { CpuFill16(0, (void *)(BG_PLTT), BG_PLTT_SIZE); ResetOamRange(0, 128); @@ -2321,3 +2320,10 @@ u16 CountBattledRematchTeams(u16 trainerId) return i; } + +u16 GetBattlePartner(u16 partnerId) +{ + if (gSaveBlock1Ptr->battlePartnerOverride != PARTNER_NONE) + return gSaveBlock1Ptr->battlePartnerOverride; + return partnerId; +} \ No newline at end of file diff --git a/src/battle_tower.c b/src/battle_tower.c index 6d59989ff4c..b6215501cd1 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -1952,6 +1952,11 @@ static void HandleMultiTrainerBattleEnd(void) SetMainCallback2(CB2_EndTrainerBattle); } +static void HandleMultiWildBattleEnd(void) +{ + SetMainCallback2(CB2_EndScriptedWildBattle); +} + static void HandleFacilityTrainerBattleEnd(void) { // TODO move facility battles to here @@ -1999,7 +2004,7 @@ static void HandleSpecialTrainerBattleEnd(void) SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); } -static void Task_StartMultiBattleAfterTransition(u8 taskId) +static void Task_StartMultiTrainerBattleAfterTransition(u8 taskId) { if (IsBattleTransitionDone() == TRUE) { @@ -2009,6 +2014,16 @@ static void Task_StartMultiBattleAfterTransition(u8 taskId) } } +static void Task_StartMultiWildBattleAfterTransition(u8 taskId) +{ + if (IsBattleTransitionDone() == TRUE) + { + gMain.savedCallback = HandleMultiWildBattleEnd; + SetMainCallback2(CB2_InitBattle); + DestroyTask(taskId); + } +} + static void Task_StartFacilityBattleAfterTransition(u8 taskId) { if (IsBattleTransitionDone() == TRUE) @@ -2031,21 +2046,18 @@ static void Task_StartSpecialBattleAfterTransition(u8 taskId) void DoMultiTrainerBattle(void) { - gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; - if (TRAINER_BATTLE_PARAM.battleOpponentA != TRAINER_NONE) // is not against wild pokemon - { - gBattleTypeFlags |= BATTLE_TYPE_TRAINER; - } + u16 partnerId; + gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; + if (TRAINER_BATTLE_PARAM.battleOpponentB != TRAINER_NONE) // is 2 vs 2 not 2 vs 1 { gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS; } - DebugPrintfLevel(MGBA_LOG_DEBUG, "flags: %x", gBattleTypeFlags); - gPartnerTrainerId = TRAINER_PARTNER(TRAINER_BATTLE_PARAM.battlePartner); // implement override for partner id + gPartnerTrainerId = TRAINER_PARTNER(GetBattlePartner(TRAINER_BATTLE_PARAM.battlePartner)); FillPartnerParty(gPartnerTrainerId); - CreateTask(Task_StartMultiBattleAfterTransition, 1); + CreateTask(Task_StartMultiTrainerBattleAfterTransition, 1); /* might be redundant with the other music @@ -2054,11 +2066,22 @@ void DoMultiTrainerBattle(void) PlayMapChosenOrBattleBGM(0); } */ + + BattleTransition_StartOnField(GetTrainerBattleTransition()); +} - if (TRAINER_BATTLE_PARAM.battleOpponentA != TRAINER_NONE) - BattleTransition_StartOnField(GetTrainerBattleTransition()); - else - BattleTransition_StartOnField(GetWildBattleTransition()); +void DoMultiWildBattle(void) +{ + gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; + + gPartnerTrainerId = TRAINER_PARTNER(GetBattlePartner(TRAINER_BATTLE_PARAM.battlePartner)); + + FillPartnerParty(gPartnerTrainerId); + CreateTask(Task_StartMultiWildBattleAfterTransition, 1); + + PlayMapChosenOrBattleBGM(0); + + BattleTransition_StartOnField(GetWildBattleTransition()); } void DoFacilityTrainerBattle(void) diff --git a/src/scrcmd.c b/src/scrcmd.c index 533131c6857..f3e14759cbb 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -2488,3 +2488,15 @@ void ScriptSetDoubleBattleFlag(struct ScriptContext *ctx) { sIsScriptedWildDouble = TRUE; } + +void SetBattlePartner(struct ScriptContext *ctx) +{ + u16 partnerId = ScriptReadHalfword(ctx); + + gSaveBlock1Ptr->battlePartnerOverride = partnerId; +} + +void ClearBattlePartner(struct ScriptContext *ctx) +{ + gSaveBlock1Ptr->battlePartnerOverride = PARTNER_NONE; +} From c92b4f33c346c73022b41983b324ec0485f3e4f5 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 27 Dec 2024 17:40:19 +0100 Subject: [PATCH 21/39] Revert multi battle integration part 1 This reverts commit 54acc565abe168f40b984a3f5882a85fa305640a 0c3f30283defc0fac98dffa09dcf3c0b7c0e150c 0d447f17585757ffca1ac2034a7c194e5fb98c19 --- asm/macros/event.inc | 42 +++--- data/maps/LavaridgeTown_Gym_1F/scripts.inc | 20 +-- data/maps/Route102/scripts.inc | 5 +- data/scripts/trainer_battle.inc | 16 +-- data/specials.inc | 3 - include/battle_setup.h | 14 +- include/battle_tower.h | 2 - include/constants/battle.h | 2 +- include/constants/battle_partner.h | 1 - include/event_scripts.h | 2 - include/global.h | 1 - src/battle_setup.c | 99 +++---------- src/battle_tower.c | 160 ++++++--------------- src/data/battle_partners.h | 80 ----------- src/data/battle_partners.party | 37 ----- src/party_menu.c | 16 --- src/scrcmd.c | 12 -- 17 files changed, 101 insertions(+), 411 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index d270e23587a..6e531896115 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -681,20 +681,20 @@ .endm NULL = 0 - OBJ_ID_NONE = 0 + NO_OBJ_ID = 0 + NO_TRAINER = 0 @ Configures the arguments for a trainer battle, then jumps to the appropriate script in scripts/trainer_battle.inc - .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, isTrainerHill:req, isTrainerPyramid:req, battlePartner:req, mutliChooseMon:req, multiChooseCancel:req + .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, isTrainerHill:req, isTrainerPyramid:req, isMulti:req .byte 0x5c .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 \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif - .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif - .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 5); .endif - .ifgt \mutliChooseMon; .set trainerbattle_flags, trainerbattle_flags | (1 << 6); .endif - .ifgt \multiChooseCancel; .set trainerbattle_flags, trainerbattle_flags | (1 << 7); .endif + .ifgt \isMulti; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif + .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 5); .endif + .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 6); .endif .byte trainerbattle_flags .byte \localIdA @ objEventLocalIdA .2byte \trainer_a @ battleOpponentA @@ -708,18 +708,17 @@ .4byte \event_script_b @ retAddrB .4byte \victory_text @ victoryText .4byte \cannot_battle @ cannotBattle - .4byte \battlePartner @ battlePartner .endm @ 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 OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .else - 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE .endif .endm @@ -727,31 +726,31 @@ @ 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 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .else - 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE, 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 OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE .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 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, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle OBJ_ID_NONE, \trainer, NULL, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, PARTNER_NONE, FALSE, FALSE + trainerbattle NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE .endm .macro trainerbattle_2v2 trainer_a:req, intro_text_a:req, trainer_b:req, intro_text_b:req - trainerbattle OBJ_ID_NONE, \trainer_a, \intro_text_a, NULL, NULL, OBJ_ID_NONE, \trainer_b, \intro_text_b, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, PARTNER_NONE + trainerbattle NO_OBJ_ID, \trainer_a, \intro_text_a, NULL, NULL, NO_OBJ_ID, \trainer_b, \intro_text_b, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE .endm @ Starts a double battle with the player against two trainers @@ -2279,12 +2278,3 @@ .macro setwilddoubleflag callnative ScriptSetDoubleBattleFlag .endm - - .macro setbattlepartner partnerId:req - callnative SetBattlePartner - .2byte \partnerId - .endm - - .macro clearbattlepartner - callnative ClearBattlePartner - .endm \ No newline at end of file diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index e624c5e548f..b0a20cec59a 100644 --- a/data/maps/LavaridgeTown_Gym_1F/scripts.inc +++ b/data/maps/LavaridgeTown_Gym_1F/scripts.inc @@ -49,7 +49,7 @@ LavaridgeTown_Gym_1F_EventScript_EndCheckBuryTrainers:: return LavaridgeTown_Gym_1F_EventScript_Flannery:: - @trainerbattle_single TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryIntro, LavaridgeTown_Gym_1F_Text_FlanneryDefeat, LavaridgeTown_Gym_1F_EventScript_FlanneryDefeated, NO_MUSIC + trainerbattle_single TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryIntro, LavaridgeTown_Gym_1F_Text_FlanneryDefeat, LavaridgeTown_Gym_1F_EventScript_FlanneryDefeated, NO_MUSIC specialvar VAR_RESULT, ShouldTryRematchBattle goto_if_eq VAR_RESULT, TRUE, LavaridgeTown_Gym_1F_EventScript_FlanneryRematch goto_if_unset FLAG_RECEIVED_TM_OVERHEAT, LavaridgeTown_Gym_1F_EventScript_GiveOverheat2 @@ -99,12 +99,12 @@ LavaridgeTown_Gym_1F_EventScript_GiveOverheat:: return LavaridgeTown_Gym_1F_EventScript_FlanneryRematch:: - @trainerbattle_rematch_double TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryPreRematch, LavaridgeTown_Gym_1F_Text_FlanneryRematchDefeat, LavaridgeTown_Gym_1F_Text_FlanneryRematchNeedTwoMons + trainerbattle_rematch_double TRAINER_FLANNERY_1, LavaridgeTown_Gym_1F_Text_FlanneryPreRematch, LavaridgeTown_Gym_1F_Text_FlanneryRematchDefeat, LavaridgeTown_Gym_1F_Text_FlanneryRematchNeedTwoMons msgbox LavaridgeTown_Gym_1F_Text_FlanneryPostRematch, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Cole:: - @trainerbattle LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, 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 LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_AxlePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Keegan:: - @trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_KeeganPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Danielle:: - @trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_DaniellePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Gerald:: - @trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_GeraldPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jace:: - @trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JacePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jeff:: - @trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JeffPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Eli:: - @trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_EliPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index 99ed0b8f3be..4f782fc7c2c 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -64,14 +64,13 @@ Route102_EventScript_Rick:: end Route102_EventScript_Tiana:: - @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, isTrainerHill:req, isTrainerPyramid:req, mutliChooseMon:req, battlePartner:req - trainerbattle OBJ_ID_NONE, TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, PARTNER_STEVEN, TRUE, TRUE + trainerbattle_single TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated Route102_EventScript_TianaMsg:: msgbox Route102_Text_TianaPostBattle, MSGBOX_AUTOCLOSE end Route102_EventScript_Allen:: - trainerbattle OBJ_ID_NONE, TRAINER_ALLEN, Route102_Text_AllenIntro, Route102_Text_AllenDefeated, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, PARTNER_PHTEVEN, FALSE, FALSE + trainerbattle_single TRAINER_ALLEN, Route102_Text_AllenIntro, Route102_Text_AllenDefeated msgbox Route102_Text_AllenPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index 928478e6161..a0909dc25d9 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -221,22 +221,14 @@ EventScript_SaveMonOrder:: return EventScript_DoSpecialTrainerBattle:: + setvar VAR_0x8004, SPECIAL_BATTLE_MULTI + setvar VAR_0x8005, MULTI_BATTLE_2_VS_2 | MULTI_BATTLE_CHOOSE_MONS + setvar VAR_0x8006, PARTNER_STEVEN special DoSpecialTrainerBattle waitstate return -EventScript_DoMultiTrainerBattle:: - special DoMultiTrainerBattle - waitstate - return - -EventScript_DoFacilityTrainerBattle:: - special DoFacilityTrainerBattle - waitstate - return - EventScript_SaveSelectedParty:: setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY special CallFrontierUtilFunc - return - + return \ No newline at end of file diff --git a/data/specials.inc b/data/specials.inc index 8085445b599..f12f4e20e50 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -555,6 +555,3 @@ gSpecials:: def_special Script_GetChosenMonDefensiveEVs def_special Script_GetChosenMonOffensiveIVs def_special Script_GetChosenMonDefensiveIVs - def_special DoMultiTrainerBattle - def_special DoFacilityTrainerBattle - def_special DoMultiWildBattle diff --git a/include/battle_setup.h b/include/battle_setup.h index 47d7ddcc39f..0311e56ff3b 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -25,10 +25,10 @@ typedef union PACKED TrainerBattleParameterUnion u8 isRematch:1; u8 isTrainerHill:1; u8 isTrainerPyramid:1; + u8 isMultiBattle:1; u8 playMusicA:1; u8 playMusicB:1; - u8 multiChooseMons:1; - u8 multiChooseCancel:1; + u8 padding:1; u8 objEventLocalIdA; u16 battleOpponentA; u8* introTextA; @@ -41,16 +41,15 @@ typedef union PACKED TrainerBattleParameterUnion u8* battleScriptRetAddrB; u8* victoryText; u8* cannotBattleText; - u16 battlePartner; } params; u8 data[sizeof(struct Parameters)]; } TrainerBattleParameterU; -#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %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\npartner: %d\nchoose mons: %d\nallow cancel: %d\n", \ - battleParameter->params.isDoubleBattle, battleParameter->params.playMusicA, battleParameter->params.playMusicB, battleParameter->params.isRematch, battleParameter->params.isTrainerHill, battleParameter->params.isTrainerPyramid, \ +#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %d\nisMultiBattle: %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.isTrainerHill, battleParameter->params.isTrainerPyramid, battleParameter->params.isMultiBattle, 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, battleParameter->params.battlePartner, battleParameter->params.multiChooseMons, battleParameter->params.multiChooseCancel) + battleParameter->params.victoryText, battleParameter->params.cannotBattleText) typedef struct TrainerBattleScriptStack { @@ -127,8 +126,5 @@ 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); -void CB2_EndTrainerBattle(void); -void CB2_EndScriptedWildBattle(void); -u16 GetBattlePartner(u16 partnerId); #endif // GUARD_BATTLE_SETUP_H diff --git a/include/battle_tower.h b/include/battle_tower.h index 26fab390732..074fccf3a5f 100644 --- a/include/battle_tower.h +++ b/include/battle_tower.h @@ -78,6 +78,4 @@ bool32 ValidateBattleTowerRecord(u8 recordId); // unused void TrySetLinkBattleTowerEnemyPartyLevel(void); void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 otID, u32 flags, struct Pokemon *dst); -void DoMultiTrainerBattle(void); -void DoFacilityTrainerBattle(void); #endif //GUARD_BATTLE_TOWER_H diff --git a/include/constants/battle.h b/include/constants/battle.h index a2be627be47..91289f718eb 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 && TRAINER_BATTLE_PARAM.battleOpponentB == 0)) +#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) diff --git a/include/constants/battle_partner.h b/include/constants/battle_partner.h index 402f2d0500c..5622349a888 100644 --- a/include/constants/battle_partner.h +++ b/include/constants/battle_partner.h @@ -4,6 +4,5 @@ #define PARTNER_NONE 0 #define PARTNER_STEVEN 1 -#define PARTNER_PHTEVEN 2 #endif // GUARD_CONSTANTS_BATTLE_PARTNERS_H diff --git a/include/event_scripts.h b/include/event_scripts.h index 9293dea9638..eb1c075ca56 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -59,8 +59,6 @@ extern const u8 EventScript_LoadPlayerParty[]; extern const u8 EventScript_ReducePlayerPartyToSelectedMons[]; extern const u8 EventScript_SaveMonOrder[]; extern const u8 EventScript_DoSpecialTrainerBattle[]; -extern const u8 EventScript_DoMultiTrainerBattle[]; -extern const u8 EventScript_DoFacilityTrainerBattle[]; extern const u8 EventScript_SaveSelectedParty[]; extern const u8 BerryTreeScript[]; diff --git a/include/global.h b/include/global.h index 1c1856a337e..d872d9d303a 100644 --- a/include/global.h +++ b/include/global.h @@ -1084,7 +1084,6 @@ struct SaveBlock1 /*0x3???*/ struct TrainerHillSave trainerHill; #endif //FREE_TRAINER_HILL /*0x3???*/ struct WaldaPhrase waldaPhrase; - /*0x3???*/ u16 battlePartnerOverride; // sizeof: 0x3??? }; diff --git a/src/battle_setup.c b/src/battle_setup.c index fe708751680..0d1a5fefa66 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -42,7 +42,6 @@ #include "item.h" #include "constants/battle_frontier.h" #include "constants/battle_setup.h" -#include "constants/battle_tower.h" #include "constants/game_stat.h" #include "constants/items.h" #include "constants/songs.h" @@ -79,6 +78,7 @@ static void DoBattlePikeWildBattle(void); static void DoSafariBattle(void); static void DoStandardWildBattle(bool32 isDouble); static void CB2_EndWildBattle(void); +static void CB2_EndScriptedWildBattle(void); static void TryUpdateGymLeaderRematchFromWild(void); static void TryUpdateGymLeaderRematchFromTrainer(void); static void CB2_GiveStarter(void); @@ -86,6 +86,7 @@ static void CB2_StartFirstBattle(void); static void CB2_EndFirstBattle(void); static void SaveChangesToPlayerParty(void); static void HandleBattleVariantEndParty(void); +static void CB2_EndTrainerBattle(void); static bool32 IsPlayerDefeated(u32 battleOutcome); #if FREE_MATCH_CALL == FALSE static u16 GetRematchTrainerId(u16 trainerId); @@ -728,7 +729,7 @@ static void CB2_EndWildBattle(void) } } -void CB2_EndScriptedWildBattle(void) +static void CB2_EndScriptedWildBattle(void) { CpuFill16(0, (void *)(BG_PLTT), BG_PLTT_SIZE); ResetOamRange(0, 128); @@ -1228,80 +1229,27 @@ void SetMapVarsToTrainerB(void) #define PUSH(script) PtrStackPushU8(scrStack, script); -#include "party_menu.h" - -const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack *scrStack, bool16 isApproaching) +const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack *scrStack) { - - if (!isApproaching) - { - SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why - PUSH(EventScript_LockSnippet); - PUSH(EventScript_RevealTrainerSnippet); - - if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { - PUSH(EventScript_GotoPostBattleScriptSnippet); - return NULL; - } - - } if (TRAINER_BATTLE_PARAM.playMusicA) { PUSH(EventScript_PlayTrainerEncounterMusicSnippet); } - if (isApproaching) - { - PUSH(EventScript_TrainerApproachSnippet); - - if (TRAINER_BATTLE_PARAM.introTextA != NULL) - { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); - } + PUSH(EventScript_TrainerApproachSnippet); - if (TryPrepareSecondApproachingTrainer2()) { - SetMapVarsToTrainerB(); - if (TRAINER_BATTLE_PARAM.isTrainerPyramid) - { - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); - } - - if (TRAINER_BATTLE_PARAM.isTrainerHill) - { - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); - } - - PUSH(EventScript_PrepareSecondTrainerApproachSnippet); - if (TRAINER_BATTLE_PARAM.playMusicB) - { - PUSH(EventScript_PlayTrainerEncounterMusicSnippet); - } - - PUSH(EventScript_TrainerApproachSnippet); - - if (TRAINER_BATTLE_PARAM.introTextB) - { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); - } - } - } - else + if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - if (TRAINER_BATTLE_PARAM.introTextA != NULL) - { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); - } + PUSH(EventScript_ShowTrainerIntroMsgSnippet); } PUSH(EventScript_SavePlayerParty); - - if (TRAINER_BATTLE_PARAM.multiChooseMons) - { - PUSH(EventScript_ChooseHalfPartyForBattle); - PUSH(EventScript_ReducePlayerPartyToSelectedMons); - } + PUSH(EventScript_ChooseHalfPartyForBattle); + PUSH(EventScript_LoadPlayerParty); + PUSH(EventScript_SavePlayerParty); + PUSH(EventScript_ReducePlayerPartyToSelectedMons); PUSH(EventScript_SaveMonOrder); - PUSH(EventScript_DoMultiTrainerBattle); + PUSH(EventScript_DoSpecialTrainerBattle); PUSH(EventScript_SaveSelectedParty); PUSH(EventScript_LoadPlayerParty); @@ -1310,9 +1258,9 @@ const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - if (TRAINER_BATTLE_PARAM.battlePartner != PARTNER_NONE) + if (TRAINER_BATTLE_PARAM.isMultiBattle) { - return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack, TRUE); + return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); } if (TRAINER_BATTLE_PARAM.isTrainerPyramid) @@ -1376,9 +1324,9 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, { return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); } - if (TRAINER_BATTLE_PARAM.battlePartner != PARTNER_NONE) + if (TRAINER_BATTLE_PARAM.isMultiBattle) { - return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack, FALSE); + return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); } @@ -1436,7 +1384,7 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, { PUSH(EventScript_DoRematchTrainerBattleSnippet); } - else + else { PUSH(EventScript_DoTrainerBattleSnippet); } @@ -1593,8 +1541,6 @@ static void SetBattledTrainersFlags(void) if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) FlagSet(GetTrainerBFlag()); FlagSet(GetTrainerAFlag()); - - DebugPrintfLevel(MGBA_LOG_DEBUG, "a: %d b: %d", GetTrainerAFlag(), GetTrainerBFlag()); } static void UNUSED SetBattledTrainerFlag(void) @@ -1708,9 +1654,8 @@ static void HandleBattleVariantEndParty(void) FlagClear(B_FLAG_SKY_BATTLE); } -void CB2_EndTrainerBattle(void) +static void CB2_EndTrainerBattle(void) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "here %d, %d", IsPlayerDefeated(gBattleOutcome), gBattleOutcome); HandleBattleVariantEndParty(); if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_SECRET_BASE) @@ -1731,7 +1676,6 @@ void CB2_EndTrainerBattle(void) DowngradeBadPoison(); if (!InBattlePyramid() && !InTrainerHillChallenge()) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "here2"); RegisterTrainerInMatchCall(); SetBattledTrainersFlags(); } @@ -2320,10 +2264,3 @@ u16 CountBattledRematchTeams(u16 trainerId) return i; } - -u16 GetBattlePartner(u16 partnerId) -{ - if (gSaveBlock1Ptr->battlePartnerOverride != PARTNER_NONE) - return gSaveBlock1Ptr->battlePartnerOverride; - return partnerId; -} \ No newline at end of file diff --git a/src/battle_tower.c b/src/battle_tower.c index b6215501cd1..fed05b0e4d2 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -1934,34 +1934,6 @@ static void GetOpponentIntroSpeech(void) else BufferApprenticeChallengeText(trainerId - TRAINER_RECORD_MIXING_APPRENTICE); } -static void HandleMultiTrainerBattleEnd(void) -{ - s32 i; - - RecordedBattle_SaveBattleOutcome(); - - if (!TRAINER_BATTLE_PARAM.multiChooseMons) - { - for (i = 0; i < 3; i++) // TODO magic number - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES)) - gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i]; - } - } - - SetMainCallback2(CB2_EndTrainerBattle); -} - -static void HandleMultiWildBattleEnd(void) -{ - SetMainCallback2(CB2_EndScriptedWildBattle); -} - -static void HandleFacilityTrainerBattleEnd(void) -{ - // TODO move facility battles to here - return; -} static void HandleSpecialTrainerBattleEnd(void) { @@ -1999,32 +1971,19 @@ static void HandleSpecialTrainerBattleEnd(void) case SPECIAL_BATTLE_EREADER: CopyEReaderTrainerFarewellMessage(); break; + case SPECIAL_BATTLE_MULTI: + for (i = 0; i < 3; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES)) + gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i]; + } + break; } SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); } -static void Task_StartMultiTrainerBattleAfterTransition(u8 taskId) -{ - if (IsBattleTransitionDone() == TRUE) - { - gMain.savedCallback = HandleMultiTrainerBattleEnd; - SetMainCallback2(CB2_InitBattle); - DestroyTask(taskId); - } -} - -static void Task_StartMultiWildBattleAfterTransition(u8 taskId) -{ - if (IsBattleTransitionDone() == TRUE) - { - gMain.savedCallback = HandleMultiWildBattleEnd; - SetMainCallback2(CB2_InitBattle); - DestroyTask(taskId); - } -} - -static void Task_StartFacilityBattleAfterTransition(u8 taskId) +static void Task_StartBattleAfterTransition(u8 taskId) { if (IsBattleTransitionDone() == TRUE) { @@ -2034,62 +1993,6 @@ static void Task_StartFacilityBattleAfterTransition(u8 taskId) } } -static void Task_StartSpecialBattleAfterTransition(u8 taskId) -{ - if (IsBattleTransitionDone() == TRUE) - { - gMain.savedCallback = HandleSpecialTrainerBattleEnd; - SetMainCallback2(CB2_InitBattle); - DestroyTask(taskId); - } -} - -void DoMultiTrainerBattle(void) -{ - u16 partnerId; - gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; - - if (TRAINER_BATTLE_PARAM.battleOpponentB != TRAINER_NONE) // is 2 vs 2 not 2 vs 1 - { - gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS; - } - - gPartnerTrainerId = TRAINER_PARTNER(GetBattlePartner(TRAINER_BATTLE_PARAM.battlePartner)); - - FillPartnerParty(gPartnerTrainerId); - CreateTask(Task_StartMultiTrainerBattleAfterTransition, 1); - - /* - might be redundant with the other music - if (TRAINER_BATTLE_PARAM.playMusicA) - { - PlayMapChosenOrBattleBGM(0); - } - */ - - BattleTransition_StartOnField(GetTrainerBattleTransition()); -} - -void DoMultiWildBattle(void) -{ - gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; - - gPartnerTrainerId = TRAINER_PARTNER(GetBattlePartner(TRAINER_BATTLE_PARAM.battlePartner)); - - FillPartnerParty(gPartnerTrainerId); - CreateTask(Task_StartMultiWildBattleAfterTransition, 1); - - PlayMapChosenOrBattleBGM(0); - - BattleTransition_StartOnField(GetWildBattleTransition()); -} - -void DoFacilityTrainerBattle(void) -{ - // TODO move facility stuff here - return; -} - void DoSpecialTrainerBattle(void) { s32 i; @@ -2119,7 +2022,7 @@ void DoSpecialTrainerBattle(void) FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE); break; } - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_TOWER)); break; @@ -2129,7 +2032,7 @@ void DoSpecialTrainerBattle(void) u16 itemBefore = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); SetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM, &itemBefore); } - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_SECRET_BASE)); break; @@ -2140,7 +2043,7 @@ void DoSpecialTrainerBattle(void) CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i]); gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_EREADER_TRAINER; TRAINER_BATTLE_PARAM.battleOpponentA = 0; - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_E_READER)); #endif //FREE_BATTLE_TOWER_E_READER @@ -2151,7 +2054,7 @@ void DoSpecialTrainerBattle(void) gBattleTypeFlags |= BATTLE_TYPE_DOUBLE; if (TRAINER_BATTLE_PARAM.battleOpponentA == TRAINER_FRONTIER_BRAIN) FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); CreateTask_PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_DOME)); break; @@ -2163,7 +2066,7 @@ void DoSpecialTrainerBattle(void) FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); else FillTentTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PALACE)); break; @@ -2173,7 +2076,7 @@ void DoSpecialTrainerBattle(void) FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); else FillTentTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_ARENA)); break; @@ -2182,31 +2085,58 @@ void DoSpecialTrainerBattle(void) if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES) gBattleTypeFlags |= BATTLE_TYPE_DOUBLE; FillFactoryTrainerParty(); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_FACTORY)); break; case SPECIAL_BATTLE_PIKE_SINGLE: gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER; FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PIKE)); break; case SPECIAL_BATTLE_PYRAMID: gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID; FillFrontierTrainerParty(FRONTIER_PARTY_SIZE); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID)); break; case SPECIAL_BATTLE_PIKE_DOUBLE: gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS; FillFrontierTrainersParties(1); - CreateTask(Task_StartSpecialBattleAfterTransition, 1); + CreateTask(Task_StartBattleAfterTransition, 1); PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PIKE)); break; + case SPECIAL_BATTLE_MULTI: + if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD) // Player + AI against wild mon + { + gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; + } + else if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_1) // Player + AI against one trainer + { + 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 + { + gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; + } + + gPartnerTrainerId = VarGet(gSpecialVar_0x8006) + TRAINER_PARTNER(PARTNER_NONE); + FillPartnerParty(gPartnerTrainerId); + CreateTask(Task_StartBattleAfterTransition, 1); + PlayMapChosenOrBattleBGM(0); + if (gSpecialVar_0x8005 & MULTI_BATTLE_2_VS_WILD) + BattleTransition_StartOnField(GetWildBattleTransition()); + else + BattleTransition_StartOnField(GetTrainerBattleTransition()); + + if (gSpecialVar_0x8005 & MULTI_BATTLE_CHOOSE_MONS) // Skip mons restoring(done in the script) + gBattleScripting.specialTrainerBattleType = 0xFF; + break; } } diff --git a/src/data/battle_partners.h b/src/data/battle_partners.h index d6b01f42291..ae0b753cb3b 100644 --- a/src/data/battle_partners.h +++ b/src/data/battle_partners.h @@ -103,83 +103,3 @@ }, }, }, -#line 45 - [PARTNER_PHTEVEN] = - { -#line 46 - .trainerName = _("PHTEVEN"), -#line 47 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 48 - .trainerPic = TRAINER_BACK_PIC_STEVEN, - .encounterMusic_gender = -#line 50 - TRAINER_ENCOUNTER_MUSIC_MALE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 52 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 56 - .ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252), -#line 55 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 54 - .lvl = 43, -#line 53 - .nature = NATURE_IMPISH, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 57 - MOVE_TOXIC, - MOVE_AERIAL_ACE, - MOVE_PROTECT, - MOVE_STEEL_WING, - }, - }, - { -#line 62 - .species = SPECIES_METANG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 66 - .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), -#line 65 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 64 - .lvl = 42, -#line 63 - .nature = NATURE_BRAVE, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 67 - MOVE_LIGHT_SCREEN, - MOVE_PSYCHIC, - MOVE_REFLECT, - MOVE_METAL_CLAW, - }, - }, - { -#line 72 - .species = SPECIES_AGGRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 76 - .ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6), -#line 75 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 74 - .lvl = 44, -#line 73 - .nature = NATURE_ADAMANT, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 77 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_SOLAR_BEAM, - MOVE_DRAGON_CLAW, - }, - }, - }, - }, diff --git a/src/data/battle_partners.party b/src/data/battle_partners.party index 15758e9ff9c..e1ecfe35faa 100644 --- a/src/data/battle_partners.party +++ b/src/data/battle_partners.party @@ -41,40 +41,3 @@ EVs: 252 Atk / 252 SpA / 6 SpD - Protect - Solar Beam - Dragon Claw - -=== PARTNER_PHTEVEN === -Name: PHTEVEN -Class: Rival -Pic: Steven -Gender: Male -Music: Male - -Skarmory -Impish Nature -Level: 43 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -EVs: 252 HP / 6 SpA / 252 SpD -- Toxic -- Aerial Ace -- Protect -- Steel Wing - -Metang -Brave Nature -Level: 42 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -EVs: 252 Atk / 252 Def / 6 SpA -- Light Screen -- Psychic -- Reflect -- Metal Claw - -Aggron -Adamant Nature -Level: 44 -IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe -EVs: 252 Atk / 252 SpA / 6 SpD -- Thunder -- Protect -- Solar Beam -- Dragon Claw \ No newline at end of file diff --git a/src/party_menu.c b/src/party_menu.c index 76a8395f85a..c46c74393f7 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -506,7 +506,6 @@ static bool8 SetUpFieldMove_Dive(void); void TryItemHoldFormChange(struct Pokemon *mon); static void ShowMoveSelectWindow(u8 slot); static void Task_HandleWhichMoveInput(u8 taskId); -static void UpdateSelectedOrderFromParty(void); // static const data #include "data/party_menu.h" @@ -1382,13 +1381,7 @@ static void Task_ClosePartyMenuAndSetCB2(u8 taskId) if (!gPaletteFade.active) { if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE) - { UpdatePartyToFieldOrder(); - } - else if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF) - { - UpdateSelectedOrderFromParty(); - } if (sPartyMenuInternal->exitCallback != NULL) SetMainCallback2(sPartyMenuInternal->exitCallback); @@ -7441,15 +7434,6 @@ static void UpdatePartyToFieldOrder(void) Free(partyBuffer); } -static void UpdateSelectedOrderFromParty(void) -{ - u8 i; - for (i = 0; i < MAX_FRONTIER_PARTY_SIZE; i++) - { - gSelectedOrderFromParty[i] = i + 1; - } -} - static void UNUSED SwitchAliveMonIntoLeadSlot(void) { u8 i; diff --git a/src/scrcmd.c b/src/scrcmd.c index f3e14759cbb..533131c6857 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -2488,15 +2488,3 @@ void ScriptSetDoubleBattleFlag(struct ScriptContext *ctx) { sIsScriptedWildDouble = TRUE; } - -void SetBattlePartner(struct ScriptContext *ctx) -{ - u16 partnerId = ScriptReadHalfword(ctx); - - gSaveBlock1Ptr->battlePartnerOverride = partnerId; -} - -void ClearBattlePartner(struct ScriptContext *ctx) -{ - gSaveBlock1Ptr->battlePartnerOverride = PARTNER_NONE; -} From f4e57fdabf61f21fba928603f2c4f035c419c73e Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 27 Dec 2024 19:27:51 +0100 Subject: [PATCH 22/39] detach multi battles from regular 'trainerbattle' macro --- asm/macros/battle_frontier/battle_tower.inc | 10 +-- asm/macros/event.inc | 51 ++++++------- data/maps/LavaridgeTown_Gym_1F/scripts.inc | 16 ++-- data/maps/Route102/scripts.inc | 8 +- data/script_cmd_table.inc | 1 + data/scripts/trainer_battle.inc | 37 --------- include/battle_setup.h | 34 ++++++--- include/event_scripts.h | 8 -- src/battle_setup.c | 84 ++++++++------------- src/scrcmd.c | 7 ++ src/trainer_see.c | 2 +- 11 files changed, 103 insertions(+), 155 deletions(-) diff --git a/asm/macros/battle_frontier/battle_tower.inc b/asm/macros/battle_frontier/battle_tower.inc index 8d76cbd64b0..56c0ff5fc13 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, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons - @trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ 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, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ 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, 0, \trainer1Id, NULL, \trainer1LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ set first trainer mons - @trainerbattle TRAINER_BATTLE_SET_TRAINER_B, 0, \trainer2Id, NULL, \trainer2LoseText, NULL, 0, NULL, NULL, NULL, NULL, NULL @ 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/event.inc b/asm/macros/event.inc index 6e531896115..01bbb4e105a 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -681,20 +681,18 @@ .endm NULL = 0 - NO_OBJ_ID = 0 - NO_TRAINER = 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 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, isTrainerHill:req, isTrainerPyramid:req, isMulti:req + .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, isTrainerHill:req, isTrainerPyramid:req .byte 0x5c .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 \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif - .ifgt \isMulti; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif - .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 5); .endif - .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 6); .endif + .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif + .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 5); .endif .byte trainerbattle_flags .byte \localIdA @ objEventLocalIdA .2byte \trainer_a @ battleOpponentA @@ -714,11 +712,11 @@ @ 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE .elseif \music == TRUE - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE .else - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE .endif .endm @@ -726,42 +724,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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE .elseif \music == TRUE - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE .else - trainerbattle NO_OBJ_ID, \trainer, \intro_text, \lose_text, \event_script, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + 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, 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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE + trainerbattle OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE .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 NO_OBJ_ID, \trainer, \intro_text, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE + 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, FALSE, FALSE .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle NO_OBJ_ID, \trainer, NULL, \lose_text, NULL, NO_OBJ_ID, NO_TRAINER, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE - .endm - - .macro trainerbattle_2v2 trainer_a:req, intro_text_a:req, trainer_b:req, intro_text_b:req - trainerbattle NO_OBJ_ID, \trainer_a, \intro_text_a, NULL, NULL, NO_OBJ_ID, \trainer_b, \intro_text_b, NULL, NULL, NULL, NULL, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE - .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, FALSE, FALSE .endm @ Starts a trainer battle using the battle information stored in RAM (usually by the scripts in trainer_battle.inc, which @@ -1862,6 +1845,14 @@ _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 + @ Supplementary .macro goto_if_unset flag:req, dest:req diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index b0a20cec59a..7854f5d0c5d 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 LOCALID_COLE, TRAINER_COLE, LavaridgeTown_Gym_1F_Text_ColeIntro, LavaridgeTown_Gym_1F_Text_ColeDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, 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 LOCALID_AXLE, TRAINER_AXLE, LavaridgeTown_Gym_1F_Text_AxleIntro, LavaridgeTown_Gym_1F_Text_AxleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_AxlePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Keegan:: - trainerbattle LOCALID_KEEGAN, TRAINER_KEEGAN, LavaridgeTown_Gym_B1F_Text_KeeganIntro, LavaridgeTown_Gym_B1F_Text_KeeganDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_KeeganPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Danielle:: - trainerbattle LOCALID_DANIELLE, TRAINER_DANIELLE, LavaridgeTown_Gym_1F_Text_DanielleIntro, LavaridgeTown_Gym_1F_Text_DanielleDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_DaniellePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_1F_EventScript_Gerald:: - trainerbattle LOCALID_GERALD, TRAINER_GERALD, LavaridgeTown_Gym_1F_Text_GeraldIntro, LavaridgeTown_Gym_1F_Text_GeraldDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_1F_Text_GeraldPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jace:: - trainerbattle LOCALID_JACE, TRAINER_JACE, LavaridgeTown_Gym_B1F_Text_JaceIntro, LavaridgeTown_Gym_B1F_Text_JaceDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JacePostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Jeff:: - trainerbattle LOCALID_JEFF, TRAINER_JEFF, LavaridgeTown_Gym_B1F_Text_JeffIntro, LavaridgeTown_Gym_B1F_Text_JeffDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_JeffPostBattle, MSGBOX_AUTOCLOSE end LavaridgeTown_Gym_B1F_EventScript_Eli:: - trainerbattle LOCALID_ELI, TRAINER_ELI, LavaridgeTown_Gym_B1F_Text_EliIntro, LavaridgeTown_Gym_B1F_Text_EliDefeat, LavaridgeTown_Gym_EventScript_CheckTrainerScript, NO_OBJ_ID, 0, 0, 0, 0, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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, FALSE, FALSE msgbox LavaridgeTown_Gym_B1F_Text_EliPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index 4f782fc7c2c..a9326e40c53 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -64,13 +64,17 @@ Route102_EventScript_Rick:: end Route102_EventScript_Tiana:: - trainerbattle_single TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated + special ChooseHalfPartyForBattle + waitstate + multi_2_vs_2 TRAINER_TIANA, Route102_Text_TianaDefeated, TRAINER_ALLEN, Route102_Text_AllenDefeated, PARTNER_STEVEN Route102_EventScript_TianaMsg:: msgbox Route102_Text_TianaPostBattle, MSGBOX_AUTOCLOSE end Route102_EventScript_Allen:: - trainerbattle_single TRAINER_ALLEN, Route102_Text_AllenIntro, Route102_Text_AllenDefeated + special ChooseHalfPartyForBattle + waitstate + multi_2_vs_1 TRAINER_TIANA, Route102_Text_TianaDefeated, PARTNER_STEVEN msgbox Route102_Text_AllenPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/script_cmd_table.inc b/data/script_cmd_table.inc index 711b118cc6e..3e60e8afcc8 100644 --- a/data/script_cmd_table.inc +++ b/data/script_cmd_table.inc @@ -229,6 +229,7 @@ gScriptCmdTable:: .4byte ScrCmd_bufferitemnameplural @ 0xe2 .4byte ScrCmd_dynmultichoice @ 0xe3 .4byte ScrCmd_dynmultipush @ 0xe4 + .4byte ScrCmd_setmultitrainerbattle @ 0xe5 gScriptCmdTableEnd:: .4byte ScrCmd_nop diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index a0909dc25d9..9224a48a7cc 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -195,40 +195,3 @@ EventScript_EndTrainerBattleSnippet:: gotobeatenscript releaseall end - -EventScript_SavePlayerParty:: - special SavePlayerParty - return - -EventScript_ChooseHalfPartyForBattle:: - fadescreen FADE_TO_BLACK - special ChooseHalfPartyForBattle - waitstate - return - -EventScript_LoadPlayerParty:: - special LoadPlayerParty - return - -EventScript_ReducePlayerPartyToSelectedMons:: - special ReducePlayerPartyToSelectedMons - return - -EventScript_SaveMonOrder:: - setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_DATA - setvar VAR_0x8005, FRONTIER_DATA_SELECTED_MON_ORDER - special CallFrontierUtilFunc @ saves the mon order, so the non-selected mons get restored afterwards - return - -EventScript_DoSpecialTrainerBattle:: - setvar VAR_0x8004, SPECIAL_BATTLE_MULTI - setvar VAR_0x8005, MULTI_BATTLE_2_VS_2 | MULTI_BATTLE_CHOOSE_MONS - setvar VAR_0x8006, PARTNER_STEVEN - special DoSpecialTrainerBattle - waitstate - return - -EventScript_SaveSelectedParty:: - setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY - special CallFrontierUtilFunc - return \ No newline at end of file diff --git a/include/battle_setup.h b/include/battle_setup.h index 0311e56ff3b..687eb407566 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -17,18 +17,17 @@ struct RematchTrainer the layout of the first byte can be confusing here isDoubleBattle is the least lsb. msb is in the padding. */ -typedef union PACKED TrainerBattleParameterUnion +typedef union PACKED TrainerBattleParameter { - struct PACKED Parameters + struct PACKED _TrainerBattleParameter { u8 isDoubleBattle:1; u8 isRematch:1; u8 isTrainerHill:1; u8 isTrainerPyramid:1; - u8 isMultiBattle:1; u8 playMusicA:1; u8 playMusicB:1; - u8 padding:1; + u8 padding:2; u8 objEventLocalIdA; u16 battleOpponentA; u8* introTextA; @@ -42,11 +41,27 @@ typedef union PACKED TrainerBattleParameterUnion u8* victoryText; u8* cannotBattleText; } params; - u8 data[sizeof(struct Parameters)]; -} TrainerBattleParameterU; + u8 data[sizeof(struct _TrainerBattleParameter)]; +} TrainerBattleParameter; -#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %d\nisMultiBattle: %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.isTrainerHill, battleParameter->params.isTrainerPyramid, battleParameter->params.isMultiBattle, battleParameter->params.padding, \ +/* + 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\nisTrainerHill: %d\nisTrainerPyramid: %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.isTrainerHill, battleParameter->params.isTrainerPyramid, 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) @@ -61,7 +76,7 @@ typedef struct TrainerBattleScriptStack extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; -extern TrainerBattleParameterU gTrainerBattleParameter; +extern TrainerBattleParameter gTrainerBattleParameter; extern bool16 gHideCancelOptionOnPartySelect; extern u16 gTrainerBattleOpponent_A; extern u16 gTrainerBattleOpponent_B; @@ -120,6 +135,7 @@ void TrainerBattleLoadArgs_2(const u8* data); void TrainerBattleLoadArgsTrainerA(const u8* data); void TrainerBattleLoadArgsTrainerB(const u8* data); void TrainerBattleLoadArgsSecondTrainer(const u8* data); +void MultiTrainerBattleLoadArgs(const u8* data); void DoStandardWildBattle_Debug(void); void BattleSetup_StartTrainerBattle_Debug(void); diff --git a/include/event_scripts.h b/include/event_scripts.h index eb1c075ca56..6fcf3caae5e 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -53,14 +53,6 @@ extern const u8 EventScript_DoRematchTrainerBattleSnippet[]; extern const u8 EventScript_NotEnoughMonsForDoubleBattle[]; extern const u8 EventScript_EndTrainerBattleSnippet[]; -extern const u8 EventScript_SavePlayerParty[]; -extern const u8 EventScript_ChooseHalfPartyForBattle[]; -extern const u8 EventScript_LoadPlayerParty[]; -extern const u8 EventScript_ReducePlayerPartyToSelectedMons[]; -extern const u8 EventScript_SaveMonOrder[]; -extern const u8 EventScript_DoSpecialTrainerBattle[]; -extern const u8 EventScript_SaveSelectedParty[]; - extern const u8 BerryTreeScript[]; extern const u8 gTVBravoTrainerText00[]; diff --git a/src/battle_setup.c b/src/battle_setup.c index 0d1a5fefa66..9e32cfe41dd 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -67,7 +67,7 @@ enum { TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR, }; -struct TrainerBattleParameter +struct TrainerBattleParameterOLD { void *varPtr; u8 ptrType; @@ -110,7 +110,7 @@ EWRAM_DATA static u8 *sTrainerCannotBattleSpeech = NULL; EWRAM_DATA static u8 *sTrainerABattleScriptRetAddr = NULL; EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL; -EWRAM_DATA TrainerBattleParameterU gTrainerBattleParameter = {0}; +EWRAM_DATA TrainerBattleParameter gTrainerBattleParameter = {0}; EWRAM_DATA u16 gPartnerTrainerId = 0; EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; @@ -166,7 +166,7 @@ static const u8 sBattleTransitionTable_BattleDome[] = B_TRANSITION_FRONTIER_SQUARES_SPIRAL }; -static const struct TrainerBattleParameter sOrdinaryBattleParams[] = +static const struct TrainerBattleParameterOLD sOrdinaryBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -179,7 +179,7 @@ static const struct TrainerBattleParameter sOrdinaryBattleParams[] = {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, }; -static const struct TrainerBattleParameter sContinueScriptBattleParams[] = +static const struct TrainerBattleParameterOLD sContinueScriptBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -192,7 +192,7 @@ static const struct TrainerBattleParameter sContinueScriptBattleParams[] = {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, }; -static const struct TrainerBattleParameter sDoubleBattleParams[] = +static const struct TrainerBattleParameterOLD sDoubleBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -205,7 +205,7 @@ static const struct TrainerBattleParameter sDoubleBattleParams[] = {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, }; -static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = +static const struct TrainerBattleParameterOLD sOrdinaryNoIntroBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -218,7 +218,7 @@ static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] = {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, }; -static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = +static const struct TrainerBattleParameterOLD sContinueScriptDoubleBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -231,7 +231,7 @@ static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] = {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, }; -static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = +static const struct TrainerBattleParameterOLD sTrainerBOrdinaryBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&TRAINER_BATTLE_PARAM.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -244,7 +244,7 @@ static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] = {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, }; -static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] = +static const struct TrainerBattleParameterOLD sTrainerBContinueScriptBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&TRAINER_BATTLE_PARAM.battleOpponentB, TRAINER_PARAM_LOAD_VAL_16BIT}, @@ -258,7 +258,7 @@ static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] }; // two trainers, each with a defeat speech -static const struct TrainerBattleParameter sTrainerTwoTrainerBattleParams[] = +static const struct TrainerBattleParameterOLD sTrainerTwoTrainerBattleParams[] = { {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, {&sTrainerObjectEventLocalId, TRAINER_PARAM_CLEAR_VAL_16BIT}, @@ -1129,7 +1129,7 @@ static inline void SetPtr(const void *ptr, const void *value) *(const void **)(ptr) = value; } -static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, const u8 *data) +static void TrainerBattleLoadArgsOLD(const struct TrainerBattleParameterOLD *specs, const u8 *data) { while (1) { @@ -1166,7 +1166,7 @@ static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, co void TrainerBattleLoadArgsTrainerA(const u8* data) { - TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + TrainerBattleParameter *temp = (TrainerBattleParameter*)data; TRAINER_BATTLE_PARAM.playMusicA = temp->params.playMusicA; TRAINER_BATTLE_PARAM.objEventLocalIdA = temp->params.objEventLocalIdA; @@ -1178,7 +1178,7 @@ void TrainerBattleLoadArgsTrainerA(const u8* data) void TrainerBattleLoadArgsTrainerB(const u8* data) { - TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + TrainerBattleParameter *temp = (TrainerBattleParameter*)data; TRAINER_BATTLE_PARAM.playMusicB = temp->params.playMusicB; TRAINER_BATTLE_PARAM.objEventLocalIdB = temp->params.objEventLocalIdB; @@ -1191,7 +1191,7 @@ void TrainerBattleLoadArgsTrainerB(const u8* data) // loads trainer A parameter to trainer B. Used for second trainer in trainer_see.c void TrainerBattleLoadArgsSecondTrainer(const u8* data) { - TrainerBattleParameterU *temp = (TrainerBattleParameterU*)data; + TrainerBattleParameter *temp = (TrainerBattleParameter*)data; TRAINER_BATTLE_PARAM.playMusicB = temp->params.playMusicA; TRAINER_BATTLE_PARAM.objEventLocalIdB = temp->params.objEventLocalIdA; @@ -1204,11 +1204,24 @@ void TrainerBattleLoadArgsSecondTrainer(const u8* data) void TrainerBattleLoadArgs_2(const u8* data) { InitTrainerBattleVariables(); - memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameterU)); - sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameterU); + memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameter)); + sTrainerBattleEndScript = (u8*)data + sizeof(TrainerBattleParameter); DebugPrintTrainerParams((&gTrainerBattleParameter)); } +void MultiTrainerBattleLoadArgs(const u8* data) +{ + 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 SetMapVarsToTrainerA(void) { if (TRAINER_BATTLE_PARAM.objEventLocalIdA != 0) @@ -1229,40 +1242,8 @@ void SetMapVarsToTrainerB(void) #define PUSH(script) PtrStackPushU8(scrStack, script); -const u8* BattleSetup_ConfigureTrainerBattleMultiBattle(const u8* data, PtrStack *scrStack) -{ - if (TRAINER_BATTLE_PARAM.playMusicA) - { - PUSH(EventScript_PlayTrainerEncounterMusicSnippet); - } - - PUSH(EventScript_TrainerApproachSnippet); - - if (TRAINER_BATTLE_PARAM.introTextA != NULL) - { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); - } - - PUSH(EventScript_SavePlayerParty); - PUSH(EventScript_ChooseHalfPartyForBattle); - PUSH(EventScript_LoadPlayerParty); - PUSH(EventScript_SavePlayerParty); - PUSH(EventScript_ReducePlayerPartyToSelectedMons); - PUSH(EventScript_SaveMonOrder); - PUSH(EventScript_DoSpecialTrainerBattle); - PUSH(EventScript_SaveSelectedParty); - PUSH(EventScript_LoadPlayerParty); - - return NULL; -} - const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - if (TRAINER_BATTLE_PARAM.isMultiBattle) - { - return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); - } - if (TRAINER_BATTLE_PARAM.isTrainerPyramid) { TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); @@ -1324,11 +1305,6 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, { return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); } - if (TRAINER_BATTLE_PARAM.isMultiBattle) - { - return BattleSetup_ConfigureTrainerBattleMultiBattle(data, scrStack); - } - SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why PUSH(EventScript_LockSnippet); @@ -1505,7 +1481,7 @@ void SetUpTwoTrainersBattle(void) #define OFFSET_TRAINERID 3 bool32 GetTrainerFlagFromScriptPointer(const u8 *data) { - TrainerBattleParameterU *temp = (TrainerBattleParameterU*)(data + OPCODE_OFFSET); + TrainerBattleParameter *temp = (TrainerBattleParameter*)(data + OPCODE_OFFSET); return FlagGet(TRAINER_FLAGS_START + temp->params.battleOpponentA); } #undef OFFSET_TRAINERID diff --git a/src/scrcmd.c b/src/scrcmd.c index 533131c6857..d4eb92d74ce 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1979,6 +1979,13 @@ bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) return FALSE; } +bool8 ScrCmd_setmultitrainerbattle(struct ScriptContext *ctx) +{ + MultiTrainerBattleLoadArgs(ctx->scriptPtr); + + return FALSE; +} + bool8 ScrCmd_dotrainerbattle(struct ScriptContext *ctx) { BattleSetup_StartTrainerBattle(); diff --git a/src/trainer_see.c b/src/trainer_see.c index 821c27f38f3..db1a41b32c4 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -498,7 +498,7 @@ static u8 CheckTrainer(u8 objectEventId) if (approachDistance != 0) { - TrainerBattleParameterU* temp = (TrainerBattleParameterU*)(scriptPtr + 1); + TrainerBattleParameter* temp = (TrainerBattleParameter*)(scriptPtr + 1); if (temp->params.isDoubleBattle) { if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS) From 1f5ae4aff2471aa6ed7b4cbf141bb4d3e4b7ad41 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 28 Dec 2024 15:40:15 +0100 Subject: [PATCH 23/39] remove obsolete stuff --- src/battle_setup.c | 283 +-------------------------------------------- 1 file changed, 3 insertions(+), 280 deletions(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index 9e32cfe41dd..9126024abfe 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 TrainerBattleParameterOLD -{ - void *varPtr; - u8 ptrType; -}; - // this file's functions static void DoBattlePikeWildBattle(void); static void DoSafariBattle(void); @@ -166,114 +150,6 @@ static const u8 sBattleTransitionTable_BattleDome[] = B_TRANSITION_FRONTIER_SQUARES_SPIRAL }; -static const struct TrainerBattleParameterOLD 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 TrainerBattleParameterOLD sContinueScriptBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentA, 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 TrainerBattleParameterOLD sDoubleBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentA, 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 TrainerBattleParameterOLD sOrdinaryNoIntroBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentA, 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 TrainerBattleParameterOLD sContinueScriptDoubleBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentA, 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 TrainerBattleParameterOLD sTrainerBOrdinaryBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentB, 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 TrainerBattleParameterOLD sTrainerBContinueScriptBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentB, 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 TrainerBattleParameterOLD sTrainerTwoTrainerBattleParams[] = -{ - {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, - {&sTrainerObjectEventLocalId, TRAINER_PARAM_CLEAR_VAL_16BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentA, TRAINER_PARAM_LOAD_VAL_16BIT}, - {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, - {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, - {&TRAINER_BATTLE_PARAM.battleOpponentB, 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}, \ @@ -1036,22 +912,6 @@ 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 + TRAINER_BATTLE_PARAM.battleOpponentA; @@ -1109,61 +969,6 @@ static void InitTrainerBattleVariables(void) memset(gTrainerBattleParameter.data, 0, sizeof(gTrainerBattleParameter)); } -static inline void SetU8(void *ptr, u8 value) -{ - *(u8 *)(ptr) = value; -} - -static inline void SetU16(void *ptr, u16 value) -{ - *(u16 *)(ptr) = value; -} - -static inline void SetU32(void *ptr, u32 value) -{ - *(u32 *)(ptr) = value; -} - -static inline void SetPtr(const void *ptr, const void *value) -{ - *(const void **)(ptr) = value; -} - -static void TrainerBattleLoadArgsOLD(const struct TrainerBattleParameterOLD *specs, 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++; - } -} - void TrainerBattleLoadArgsTrainerA(const u8* data) { TrainerBattleParameter *temp = (TrainerBattleParameter*)data; @@ -1370,89 +1175,6 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, DebugPrintStack(scrStack); return NULL; - - /* - switch (TRAINER_BATTLE_PARAM.battleFlags) - { - case TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT: - return EventScript_DoNoIntroTrainerBattle; - - case TRAINER_BATTLE_DOUBLE: - SetMapVarsToTrainer(); - return EventScript_TryDoDoubleTrainerBattle; - - case TRAINER_BATTLE_CONTINUE_SCRIPT: - if (gApproachingTrainerId == 0) - SetMapVarsToTrainer(); - return EventScript_TryDoNormalTrainerBattle; - - case TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC: - SetMapVarsToTrainer(); - return EventScript_TryDoNormalTrainerBattle; - - case TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE: - case TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC: - SetMapVarsToTrainer(); - return EventScript_TryDoDoubleTrainerBattle; - -#if FREE_MATCH_CALL == FALSE - case TRAINER_BATTLE_REMATCH_DOUBLE: - SetMapVarsToTrainer(); - TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); - return EventScript_TryDoDoubleRematchBattle; - - case TRAINER_BATTLE_REMATCH: - SetMapVarsToTrainer(); - TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); - return EventScript_TryDoRematchBattle; - -#endif //FREE_MATCH_CALL - case TRAINER_BATTLE_PYRAMID: - if (gApproachingTrainerId == 0) - { - SetMapVarsToTrainer(); - TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); - } - else - { - TrainerBattleLoadArgsTrainerB(data); - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(gSpecialVar_LastTalked); - } - return EventScript_TryDoNormalTrainerBattle; - - case TRAINER_BATTLE_SET_TRAINER_A: - // explicit load ? - return sTrainerBattleEndScript; - - case TRAINER_BATTLE_SET_TRAINER_B: - TrainerBattleLoadArgsTrainerB(data); // unnecessary since should already be loaded ? - return sTrainerBattleEndScript; - - case TRAINER_BATTLE_HILL: - if (gApproachingTrainerId == 0) - { - TrainerBattleLoadArgs(sOrdinaryBattleParams, data); - SetMapVarsToTrainer(); - TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(gSpecialVar_LastTalked); - } - else - { - TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data); - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked); - } - - return EventScript_TryDoNormalTrainerBattle; - case TRAINER_BATTLE_TWO_TRAINERS_NO_INTRO: - gNoOfApproachingTrainers = 2; // set TWO_OPPONENTS gBattleTypeFlags - gApproachingTrainerId = 1; // prevent trainer approach - return EventScript_DoNoIntroTrainerBattle; - - default: - if (gApproachingTrainerId == 0) - SetMapVarsToTrainer(); - return EventScript_TryDoNormalTrainerBattle; - } - */ } void ConfigureAndSetUpOneTrainerBattle(u8 trainerObjEventId, const u8 *trainerScript) @@ -1477,14 +1199,15 @@ 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 -#define OFFSET_TRAINERID 3 + bool32 GetTrainerFlagFromScriptPointer(const u8 *data) { TrainerBattleParameter *temp = (TrainerBattleParameter*)(data + OPCODE_OFFSET); return FlagGet(TRAINER_FLAGS_START + temp->params.battleOpponentA); } -#undef OFFSET_TRAINERID + #undef OPCODE_OFFSET // Set trainer's movement type so they stop and remain facing that direction From 9b60fcc12f2b781c6500913a2cdf47d29f6d5270 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Mon, 30 Dec 2024 02:34:26 +0100 Subject: [PATCH 24/39] detach pyramid battles from regular trainer battles --- asm/macros/event.inc | 5 ++ .../scripts.inc | 2 +- data/script_cmd_table.inc | 1 + data/scripts/trainer_battle.inc | 7 +- data/scripts/trainer_hill.inc | 2 +- include/battle_setup.h | 3 + include/event_scripts.h | 1 + src/battle_setup.c | 70 ++++++++++++++---- src/scrcmd.c | 8 +++ src/script.c | 2 - src/trainer_see.c | 71 +++++++------------ 11 files changed, 104 insertions(+), 68 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 01bbb4e105a..85a49e6954d 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1853,6 +1853,11 @@ .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/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index da4bf270492..b921fafacf1 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, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL + facilitytrainerbattle TRAINER_BATTLE_PYRAMID pyramid_showhint waitmessage waitbuttonpress diff --git a/data/script_cmd_table.inc b/data/script_cmd_table.inc index 3e60e8afcc8..dca62964960 100644 --- a/data/script_cmd_table.inc +++ b/data/script_cmd_table.inc @@ -230,6 +230,7 @@ gScriptCmdTable:: .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 9224a48a7cc..0418eedb70e 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -1,8 +1,6 @@ EventScript_StartTrainerApproach:: selectapproachingtrainer lockfortrainer - return - EventScript_TrainerApproach:: special PlayTrainerEncounterMusic special DoTrainerApproach @@ -144,6 +142,11 @@ EventScript_LockSnippet:: setflag FLAG_SAFE_FOLLOWER_MOVEMENT return +EventScript_StartTrainerApproachSnippet:: + selectapproachingtrainer + lockfortrainer + return + EventScript_TrainerApproachSnippet:: special DoTrainerApproach waitstate diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 0ea3d6b6480..ab55619f6f7 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, 0, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, 0, NULL, NULL, NULL, NULL, NULL + facilitytrainerbattle TRAINER_BATTLE_HILL trainerhill_postbattletext waitmessage waitbuttonpress diff --git a/include/battle_setup.h b/include/battle_setup.h index 687eb407566..b65c008960e 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -100,6 +100,7 @@ u8 GetSpecialBattleTransition(s32 id); void ChooseStarter(void); void ResetTrainerOpponentIds(void); 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); @@ -115,6 +116,7 @@ void BattleSetup_StartTrainerBattle(void); void BattleSetup_StartRematchBattle(void); void ShowTrainerIntroSpeech(void); const u8 *BattleSetup_GetScriptAddrAfterBattle(void); +void BattleSetup_SetScriptAddAfterBattle(const u8* ptr); const u8 *BattleSetup_GetTrainerPostBattleScript(void); void ShowTrainerCantBattleSpeech(void); void PlayTrainerEncounterMusic(void); @@ -142,5 +144,6 @@ 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/event_scripts.h b/include/event_scripts.h index 6fcf3caae5e..b8b5573f06a 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -38,6 +38,7 @@ extern const u8 EventScript_TryDoDoubleRematchBattle[]; extern const u8 EventScript_TryDoRematchBattle[]; extern const u8 EventScript_LockSnippet[]; +extern const u8 EventScript_StartTrainerApproachSnippet[]; extern const u8 EventScript_TryDoNormalTrainerBattleSnippet[]; extern const u8 EventScript_RevealTrainerSnippet[]; extern const u8 EventScript_GetTrainerFlagSnippet[]; diff --git a/src/battle_setup.c b/src/battle_setup.c index 9126024abfe..c84900730bd 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -946,6 +946,24 @@ void ResetTrainerOpponentIds(void) TRAINER_BATTLE_PARAM.battleOpponentB = 0; } +void SetMapVarsToTrainerA(void) +{ + if (TRAINER_BATTLE_PARAM.objEventLocalIdA != 0) + { + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdA; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + } +} + +void SetMapVarsToTrainerB(void) +{ + if (TRAINER_BATTLE_PARAM.objEventLocalIdB != 0) + { + gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdB; + gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdB, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + } +} + static void InitTrainerBattleVariables(void) { sTrainerBattleMode = 0; @@ -1027,21 +1045,39 @@ void MultiTrainerBattleLoadArgs(const u8* data) TRAINER_BATTLE_PARAM.defeatTextB = temp->params.defeatTextB; } -void SetMapVarsToTrainerA(void) +const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 type, const u8* scriptEndPtr) { - if (TRAINER_BATTLE_PARAM.objEventLocalIdA != 0) - { - gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdA; - gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); - } -} - -void SetMapVarsToTrainerB(void) -{ - if (TRAINER_BATTLE_PARAM.objEventLocalIdB != 0) - { - gSpecialVar_LastTalked = TRAINER_BATTLE_PARAM.objEventLocalIdB; - gSelectedObjectEvent = GetObjectEventIdByLocalIdAndMap(TRAINER_BATTLE_PARAM.objEventLocalIdB, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + InitTrainerBattleVariables(); + sTrainerBattleEndScript = (u8*)scriptEndPtr; + switch (type) + { + 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; } } @@ -1215,7 +1251,6 @@ bool32 GetTrainerFlagFromScriptPointer(const u8 *data) // For trainers who spot the player this is handled by PlayerFaceApproachingTrainer void SetTrainerFacingDirection(void) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "settrainerfacingdirection:\nselected: %d\nlast talked: %d\nfacing: %d", gSelectedObjectEvent, gSpecialVar_LastTalked, gSpecialVar_Facing); struct ObjectEvent *objectEvent = &gObjectEvents[gSelectedObjectEvent]; SetTrainerMovementType(objectEvent, GetTrainerFacingDirectionMovementType(objectEvent->facingDirection)); } @@ -1445,6 +1480,11 @@ const u8 *BattleSetup_GetScriptAddrAfterBattle(void) return EventScript_TestSignpostMsg; } +void BattleSetup_SetScriptAddAfterBattle(const u8* ptr) +{ + sTrainerBattleEndScript = (u8*)ptr; +} + const u8 *BattleSetup_GetTrainerPostBattleScript(void) { if (sShouldCheckTrainerBScript) diff --git a/src/scrcmd.c b/src/scrcmd.c index d4eb92d74ce..0dc01b98074 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1979,6 +1979,14 @@ bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) return FALSE; } +bool8 ScrCmd_facilitytrainerbattle(struct ScriptContext *ctx) +{ + u8 type = ScriptReadByte(ctx); + + ctx->scriptPtr = BattleSetup_ConfigureFacilityTrainerBattle(type, ctx->scriptPtr); + return FALSE; +} + bool8 ScrCmd_setmultitrainerbattle(struct ScriptContext *ctx) { MultiTrainerBattleLoadArgs(ctx->scriptPtr); diff --git a/src/script.c b/src/script.c index d5df9feb0f8..1509888a100 100644 --- a/src/script.c +++ b/src/script.c @@ -107,7 +107,6 @@ bool8 RunScriptCommand(struct ScriptContext *ctx) } cmdCode = *(ctx->scriptPtr); - //DebugPrintfLevel(MGBA_LOG_DEBUG, "code: %x, ptr: %x\n", cmdCode, ctx->scriptPtr); ctx->scriptPtr++; func = &ctx->cmdTable[cmdCode]; @@ -244,7 +243,6 @@ bool8 ScriptContext_RunScript(void) LockPlayerFieldControls(); - //DebugPrintGlobalScriptStack; if (!RunScriptCommand(&sGlobalScriptContext)) { sGlobalScriptContextStatus = CONTEXT_SHUTDOWN; diff --git a/src/trainer_see.c b/src/trainer_see.c index db1a41b32c4..a83fd71650f 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -390,8 +390,29 @@ bool8 CheckForTrainersWantingBattle(void) break; } - //DebugPrintfLevel(MGBA_LOG_DEBUG, "NoApprTrainers: %d", gNoOfApproachingTrainers); - + // handle battle pyramid and trainer hill until properly reworked + if (InBattlePyramid()) + { + if (gNoOfApproachingTrainers > 0) + { + ResetTrainerOpponentIds(); + + gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; + gSpecialVar_LastTalked = gObjectEvents[gApproachingTrainers[0].objectEventId].localId; + BattleSetup_ConfigureFacilityTrainerBattle(TRAINER_BATTLE_PYRAMID, gApproachingTrainers[0].trainerScriptPtr + 2); + if (gNoOfApproachingTrainers > 1) + { + 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; + } + } + if (gNoOfApproachingTrainers > 0) { ResetTrainerOpponentIds(); @@ -406,7 +427,7 @@ bool8 CheckForTrainersWantingBattle(void) } BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); - ScriptContext_SetupScript(EventScript_StartTrainerApproach); + ScriptContext_SetupScript(EventScript_StartTrainerApproachSnippet); ScriptContext_PushFromStack(&trainerBattleScriptStack); LockPlayerFieldControls(); @@ -415,47 +436,6 @@ bool8 CheckForTrainersWantingBattle(void) gTrainerApproachedPlayer = TRUE; return TRUE; } - /* - if (gNoOfApproachingTrainers == 1) - { - ResetTrainerOpponentIds(); - - PtrStack trainerBattleScriptStack; - PtrStackInit(&trainerBattleScriptStack); - TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); - - BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); - ScriptContext_SetupScript(EventScript_StartTrainerApproach); - ScriptContext_PushFromStack(&trainerBattleScriptStack); - LockPlayerFieldControls(); - - gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; - gSpecialVar_LastTalked = gObjectEvents[gSelectedObjectEvent].localId; - gTrainerApproachedPlayer = TRUE; - return TRUE; - } - else if (gNoOfApproachingTrainers == 2) - { - ResetTrainerOpponentIds(); - - PtrStack trainerBattleScriptStack; - PtrStackInit(&trainerBattleScriptStack); - TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); - TrainerBattleLoadArgsSecondTrainer(gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); - - BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); - ScriptContext_SetupScript(EventScript_StartTrainerApproach); - ScriptContext_PushFromStack(&trainerBattleScriptStack); - - LockPlayerFieldControls(); - - gSelectedObjectEvent = gApproachingTrainers[0].objectEventId; - gSpecialVar_LastTalked = gObjectEvents[gSelectedObjectEvent].localId; - gApproachingTrainerId = 0; - gTrainerApproachedPlayer = TRUE; - return TRUE; - } - */ else { gTrainerApproachedPlayer = FALSE; @@ -475,8 +455,6 @@ static u8 CheckTrainer(u8 objectEventId) scriptPtr = GetTrainerHillTrainerScript(); else scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); - - //DebugPrintfLevel(MGBA_LOG_DEBUG, "script ptr: %x", scriptPtr); if (InBattlePyramid()) { @@ -923,7 +901,6 @@ void PrepareSecondApproachingTrainer(void) bool32 TryPrepareSecondApproachingTrainer2(void) { - DebugPrintfLevel(MGBA_LOG_DEBUG, "no appr: %d, id: %d", gNoOfApproachingTrainers, gApproachingTrainerId); return gNoOfApproachingTrainers > 1; } From 20817639ffc419bd78fb4c038705ea2b6e0dca3a Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 02:13:09 +0100 Subject: [PATCH 25/39] handle trainer hill --- include/battle_setup.h | 1 + src/battle_setup.c | 4 +--- src/scrcmd.c | 1 + src/trainer_see.c | 26 ++++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/battle_setup.h b/include/battle_setup.h index b65c008960e..1a93c12be2f 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -138,6 +138,7 @@ 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); diff --git a/src/battle_setup.c b/src/battle_setup.c index c84900730bd..cf43333d472 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -964,7 +964,7 @@ void SetMapVarsToTrainerB(void) } } -static void InitTrainerBattleVariables(void) +void InitTrainerBattleVariables(void) { sTrainerBattleMode = 0; if (gApproachingTrainerId == 0) @@ -1047,7 +1047,6 @@ void MultiTrainerBattleLoadArgs(const u8* data) const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 type, const u8* scriptEndPtr) { - InitTrainerBattleVariables(); sTrainerBattleEndScript = (u8*)scriptEndPtr; switch (type) { @@ -1062,7 +1061,6 @@ const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 type, const u8* scriptEn SetMapVarsToTrainerB(); TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(gSpecialVar_LastTalked); } - return EventScript_TryDoNormalTrainerBattle; case TRAINER_BATTLE_PYRAMID: if (gApproachingTrainerId == 0) diff --git a/src/scrcmd.c b/src/scrcmd.c index 0dc01b98074..4fa086e9d4d 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1983,6 +1983,7 @@ bool8 ScrCmd_facilitytrainerbattle(struct ScriptContext *ctx) { u8 type = ScriptReadByte(ctx); + InitTrainerBattleVariables(); ctx->scriptPtr = BattleSetup_ConfigureFacilityTrainerBattle(type, ctx->scriptPtr); return FALSE; } diff --git a/src/trainer_see.c b/src/trainer_see.c index a83fd71650f..24ee878d0b7 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -396,12 +396,14 @@ bool8 CheckForTrainersWantingBattle(void) 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); @@ -412,6 +414,29 @@ bool8 CheckForTrainersWantingBattle(void) 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; + } + } if (gNoOfApproachingTrainers > 0) { @@ -422,6 +447,7 @@ bool8 CheckForTrainersWantingBattle(void) TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); if (gNoOfApproachingTrainers > 1) { + gApproachingTrainerId++; TrainerBattleLoadArgsSecondTrainer(gApproachingTrainers[1].trainerScriptPtr + OPCODE_OFFSET); gApproachingTrainerId = 0; } From 6cdc290c1174b305a6d5fb1835c23c79dd9d62c0 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 02:23:47 +0100 Subject: [PATCH 26/39] remove pyramid and trainer hill from trainerbattleparam struct --- asm/macros/event.inc | 26 +++++++-------- data/maps/LavaridgeTown_Gym_1F/scripts.inc | 16 +++++----- include/battle_setup.h | 8 ++--- src/battle_setup.c | 37 ---------------------- 4 files changed, 23 insertions(+), 64 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 85a49e6954d..3082cfc3487 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -684,15 +684,13 @@ OBJ_ID_NONE = 0 @ Configures the arguments for a trainer battle, then jumps to the appropriate script in scripts/trainer_battle.inc - .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, isTrainerHill:req, isTrainerPyramid:req + .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 .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 \isTrainerHill; .set trainerbattle_flags, trainerbattle_flags | (1 << 2); .endif - .ifgt \isTrainerPyramid; .set trainerbattle_flags, trainerbattle_flags | (1 << 3); .endif - .ifgt \playMusicA; .set trainerbattle_flags, trainerbattle_flags | (1 << 4); .endif - .ifgt \playMusicB; .set trainerBattle_flags, trainerbattle_flags | (1 << 5); .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 @@ -712,11 +710,11 @@ @ 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 OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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 OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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 OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + 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 @@ -724,27 +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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE + 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 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, FALSE, FALSE + 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 OBJ_ID_NONE, \trainer, NULL, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE + 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 diff --git a/data/maps/LavaridgeTown_Gym_1F/scripts.inc b/data/maps/LavaridgeTown_Gym_1F/scripts.inc index 7854f5d0c5d..b65ebf9e485 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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 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, FALSE, FALSE + 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/include/battle_setup.h b/include/battle_setup.h index 1a93c12be2f..38e999ef86e 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -23,11 +23,9 @@ typedef union PACKED TrainerBattleParameter { u8 isDoubleBattle:1; u8 isRematch:1; - u8 isTrainerHill:1; - u8 isTrainerPyramid:1; u8 playMusicA:1; u8 playMusicB:1; - u8 padding:2; + u8 padding:4; u8 objEventLocalIdA; u16 battleOpponentA; u8* introTextA; @@ -60,8 +58,8 @@ typedef union PACKED MultiTrainerBattleParameter u8 data[sizeof(struct _MultiTrainerBattleParameter)]; } MultiTrainerBattleParameter; -#define DebugPrintTrainerParams(battleParameter) DebugPrintfLevel(MGBA_LOG_DEBUG, "\nisDouble: %d\nplayMusicA: %d\nplayMusicB: %d\nisRematch: %d\nisTrainerHill: %d\nisTrainerPyramid: %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.isTrainerHill, battleParameter->params.isTrainerPyramid, battleParameter->params.padding, \ +#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) diff --git a/src/battle_setup.c b/src/battle_setup.c index cf43333d472..df0bbd33a37 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1083,16 +1083,6 @@ const u8* BattleSetup_ConfigureFacilityTrainerBattle(u8 type, const u8* scriptEn const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, PtrStack *scrStack) { - if (TRAINER_BATTLE_PARAM.isTrainerPyramid) - { - TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); - } - - if (TRAINER_BATTLE_PARAM.isTrainerHill) - { - TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); - } - if (TRAINER_BATTLE_PARAM.playMusicA) { PUSH(EventScript_PlayTrainerEncounterMusicSnippet); @@ -1107,15 +1097,6 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P if (TryPrepareSecondApproachingTrainer2()) { SetMapVarsToTrainerB(); - if (TRAINER_BATTLE_PARAM.isTrainerPyramid) - { - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); - } - - if (TRAINER_BATTLE_PARAM.isTrainerHill) - { - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); - } PUSH(EventScript_PrepareSecondTrainerApproachSnippet); if (TRAINER_BATTLE_PARAM.playMusicB) @@ -1165,24 +1146,6 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, TRAINER_BATTLE_PARAM.battleOpponentA = GetRematchTrainerId(TRAINER_BATTLE_PARAM.battleOpponentA); } - if (TRAINER_BATTLE_PARAM.isTrainerPyramid) - { - TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); - if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) - { - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToPyramidTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); - } - } - - if (TRAINER_BATTLE_PARAM.isTrainerHill) - { - TRAINER_BATTLE_PARAM.battleOpponentA = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdA); - if (TRAINER_BATTLE_PARAM.battleOpponentB != 0) - { - TRAINER_BATTLE_PARAM.battleOpponentB = LocalIdToHillTrainerId(TRAINER_BATTLE_PARAM.objEventLocalIdB); - } - } - if (TRAINER_BATTLE_PARAM.playMusicA) { PUSH(EventScript_PlayTrainerEncounterMusicSnippet); From 4a051aed27dd3e7ae3741b8c2d15982b695b7647 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 03:12:05 +0100 Subject: [PATCH 27/39] Revert "set up some test trainers" This reverts commit bc49435b7d0c93b230b946f439eb7ff8c5013b88. --- data/maps/Route102/map.json | 30 +++++++-------- data/maps/Route102/scripts.inc | 2 +- data/maps/map_groups.json | 67 ++++++++++++++++++++++++++++++++++ src/data/wild_encounters.json | 55 ++++------------------------ 4 files changed, 88 insertions(+), 66 deletions(-) diff --git a/data/maps/Route102/map.json b/data/maps/Route102/map.json index 821a3d4c236..8ad17aae4da 100644 --- a/data/maps/Route102/map.json +++ b/data/maps/Route102/map.json @@ -53,10 +53,10 @@ }, { "graphics_id": "OBJ_EVENT_GFX_BUG_CATCHER", - "x": 16, - "y": 2, + "x": 25, + "y": 15, "elevation": 3, - "movement_type": "MOVEMENT_TYPE_FACE_DOWN", + "movement_type": "MOVEMENT_TYPE_FACE_UP", "movement_range_x": 0, "movement_range_y": 0, "trainer_type": "TRAINER_TYPE_NORMAL", @@ -66,10 +66,10 @@ }, { "graphics_id": "OBJ_EVENT_GFX_LASS", - "x": 14, - "y": 2, + "x": 8, + "y": 7, "elevation": 3, - "movement_type": "MOVEMENT_TYPE_FACE_DOWN", + "movement_type": "MOVEMENT_TYPE_FACE_DOWN_AND_RIGHT", "movement_range_x": 0, "movement_range_y": 0, "trainer_type": "TRAINER_TYPE_NORMAL", @@ -131,24 +131,20 @@ }, { "graphics_id": "OBJ_EVENT_GFX_YOUNGSTER", - "x": 14, - "y": 5, + "x": 19, + "y": 4, "elevation": 3, - "movement_type": "MOVEMENT_TYPE_FACE_UP", - "movement_range_x": 0, - "movement_range_y": 0, + "movement_type": "MOVEMENT_TYPE_FACE_DOWN", + "movement_range_x": 1, + "movement_range_y": 1, "trainer_type": "TRAINER_TYPE_NORMAL", "trainer_sight_or_berry_tree_id": "3", "script": "Route102_EventScript_Allen", "flag": "0" } ], - "warp_events": [ - - ], - "coord_events": [ - - ], + "warp_events": [], + "coord_events": [], "bg_events": [ { "type": "sign", diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index a9326e40c53..397398daee2 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -59,7 +59,7 @@ Route102_EventScript_CalvinRematch:: end Route102_EventScript_Rick:: - trainerbattle_no_intro TRAINER_RICK, Route102_Text_RickDefeated + trainerbattle_single TRAINER_RICK, Route102_Text_RickIntro, Route102_Text_RickDefeated msgbox Route102_Text_RickPostBattle, MSGBOX_AUTOCLOSE end diff --git a/data/maps/map_groups.json b/data/maps/map_groups.json index 909fddab72b..ebef431b300 100644 --- a/data/maps/map_groups.json +++ b/data/maps/map_groups.json @@ -620,5 +620,72 @@ ], "gMapGroup_IndoorRoute124": [ "Route124_DivingTreasureHuntersHouse" + ], + "connections_include_order": [ + "LittlerootTown", + "OldaleTown", + "DewfordTown", + "LavaridgeTown", + "FallarborTown", + "VerdanturfTown", + "PacifidlogTown", + "PetalburgCity", + "SlateportCity", + "MauvilleCity", + "RustboroCity", + "FortreeCity", + "LilycoveCity", + "MossdeepCity", + "SootopolisCity", + "EverGrandeCity", + "Route101", + "Route102", + "Route103", + "Route104", + "Route105", + "Route106", + "Route107", + "Route108", + "Route109", + "Route110", + "Route111", + "Route112", + "Route113", + "Route114", + "Route115", + "Route116", + "Route117", + "Route118", + "Route119", + "Route120", + "Route121", + "Route122", + "Route123", + "Route124", + "Route125", + "Route126", + "Route127", + "Route128", + "Route129", + "Route130", + "Route131", + "Route132", + "Route133", + "Route134", + "Underwater_Route105", + "Underwater_Route124", + "Underwater_Route125", + "Underwater_Route126", + "Underwater_Route127", + "Underwater_Route128", + "Underwater_Route129", + "SafariZone_Northwest", + "SafariZone_North", + "SafariZone_Southwest", + "SafariZone_South", + "SafariZone_Northeast", + "SafariZone_Southeast", + "BattleFrontier_OutsideWest", + "BattleFrontier_OutsideEast" ] } diff --git a/src/data/wild_encounters.json b/src/data/wild_encounters.json index 053c4c095f4..0b30c0f65bf 100755 --- a/src/data/wild_encounters.json +++ b/src/data/wild_encounters.json @@ -7,71 +7,30 @@ { "type": "land_mons", "encounter_rates": [ - 20, - 20, - 10, - 10, - 10, - 10, - 5, - 5, - 4, - 4, - 1, - 1 + 20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1 ] }, { "type": "water_mons", "encounter_rates": [ - 60, - 30, - 5, - 4, - 1 + 60, 30, 5, 4, 1 ] }, { "type": "rock_smash_mons", "encounter_rates": [ - 60, - 30, - 5, - 4, - 1 + 60, 30, 5, 4, 1 ] }, { "type": "fishing_mons", "encounter_rates": [ - 70, - 30, - 60, - 20, - 20, - 40, - 40, - 15, - 4, - 1 + 70, 30, 60, 20, 20, 40, 40, 15, 4, 1 ], "groups": { - "old_rod": [ - 0, - 1 - ], - "good_rod": [ - 2, - 3, - 4 - ], - "super_rod": [ - 5, - 6, - 7, - 8, - 9 - ] + "old_rod": [0, 1], + "good_rod": [2, 3, 4], + "super_rod": [5, 6, 7, 8, 9] } } ], From 634b1124e33335cebde75018bab346307f2e1147 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 03:31:15 +0100 Subject: [PATCH 28/39] cleanup --- asm/macros/event.inc | 2 +- data/script_cmd_table.inc | 4 +- data/scripts/trainer_battle.inc | 7 -- data/specials.inc | 1 - include/battle_setup.h | 5 +- include/script.h | 1 - include/stack.h | 4 +- src/battle_setup.c | 133 +++++++++++--------------------- src/scrcmd.c | 2 +- src/script.c | 6 -- src/stack.c | 2 +- src/trainer_see.c | 2 +- 12 files changed, 57 insertions(+), 112 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 3082cfc3487..df199c9be12 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -697,7 +697,7 @@ .4byte \intro_text_a @ introTextA .4byte \lose_text_a @ defeatTextA .4byte \event_script_a @ retAddrA - .byte \localIdB @ objEventLocalIdB + .byte \localIdB @ objEventLocalIdB .2byte \trainer_b @ battleOpponentB .4byte \intro_text_b @ introTextB .4byte \lose_text_b @ defeatTextB diff --git a/data/script_cmd_table.inc b/data/script_cmd_table.inc index dca62964960..3542fe44252 100644 --- a/data/script_cmd_table.inc +++ b/data/script_cmd_table.inc @@ -229,8 +229,8 @@ gScriptCmdTable:: .4byte ScrCmd_bufferitemnameplural @ 0xe2 .4byte ScrCmd_dynmultichoice @ 0xe3 .4byte ScrCmd_dynmultipush @ 0xe4 - .4byte ScrCmd_setmultitrainerbattle @ 0xe5 - .4byte ScrCmd_facilitytrainerbattle @ 0xe6 + .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 0418eedb70e..dc16a17ae1b 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 diff --git a/data/specials.inc b/data/specials.inc index f12f4e20e50..7e81da346f9 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 diff --git a/include/battle_setup.h b/include/battle_setup.h index 38e999ef86e..1135bc3e5ee 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -105,7 +105,6 @@ 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); @@ -114,7 +113,7 @@ void BattleSetup_StartTrainerBattle(void); void BattleSetup_StartRematchBattle(void); void ShowTrainerIntroSpeech(void); const u8 *BattleSetup_GetScriptAddrAfterBattle(void); -void BattleSetup_SetScriptAddAfterBattle(const u8* ptr); +void BattleSetup_SetScriptAddrAfterBattle(const u8* ptr); const u8 *BattleSetup_GetTrainerPostBattleScript(void); void ShowTrainerCantBattleSpeech(void); void PlayTrainerEncounterMusic(void); @@ -131,7 +130,7 @@ bool8 ShouldTryRematchBattle(void); bool8 IsTrainerReadyForRematch(void); void ShouldTryGetTrainerScript(void); u16 CountBattledRematchTeams(u16 trainerId); -void TrainerBattleLoadArgs_2(const u8* data); +void TrainerBattleLoadArgs(const u8* data); void TrainerBattleLoadArgsTrainerA(const u8* data); void TrainerBattleLoadArgsTrainerB(const u8* data); void TrainerBattleLoadArgsSecondTrainer(const u8* data); diff --git a/include/script.h b/include/script.h index 1248b1dfa2a..ada7c112750 100644 --- a/include/script.h +++ b/include/script.h @@ -54,7 +54,6 @@ void ScriptReturn(struct ScriptContext *ctx); u16 ScriptReadHalfword(struct ScriptContext *ctx); u32 ScriptReadWord(struct ScriptContext *ctx); u32 ScriptPeekWord(struct ScriptContext *ctx); -void ScriptConsume(struct ScriptContext *ctx, u8* buffer, u32 n); void LockPlayerFieldControls(void); void UnlockPlayerFieldControls(void); bool8 ArePlayerFieldControlsLocked(void); diff --git a/include/stack.h b/include/stack.h index 87e5f59a0a9..cf729774f3b 100644 --- a/include/stack.h +++ b/include/stack.h @@ -23,6 +23,6 @@ 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); +bool32 PtrStackPushU8(PtrStack *stack, const u8* ptr); -#endif // GUARD_STACK_H \ No newline at end of file +#endif // GUARD_STACK_H diff --git a/src/battle_setup.c b/src/battle_setup.c index df0bbd33a37..0d15a53956b 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -80,20 +80,6 @@ static void HandleRematchVarsOnBattleEnd(void); static const u8 *GetIntroSpeechOfApproachingTrainer(void); static const u8 *GetTrainerCantBattleSpeech(void); - -EWRAM_DATA static u8 sTrainerBattleMode = 0; -EWRAM_DATA u16 gTrainerBattleOpponent_A = 0; -EWRAM_DATA u16 gTrainerBattleOpponent_B = 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 *sTrainerABattleScriptRetAddr = NULL; -EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL; - EWRAM_DATA TrainerBattleParameter gTrainerBattleParameter = {0}; EWRAM_DATA u16 gPartnerTrainerId = 0; EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; @@ -966,24 +952,7 @@ void SetMapVarsToTrainerB(void) void InitTrainerBattleVariables(void) { - sTrainerBattleMode = 0; - if (gApproachingTrainerId == 0) - { - sTrainerAIntroSpeech = NULL; - sTrainerADefeatSpeech = NULL; - sTrainerABattleScriptRetAddr = NULL; - } - else - { - sTrainerBIntroSpeech = NULL; - sTrainerBDefeatSpeech = NULL; - sTrainerBBattleScriptRetAddr = NULL; - } - sTrainerObjectEventLocalId = 0; - sTrainerVictorySpeech = NULL; - sTrainerCannotBattleSpeech = NULL; sTrainerBattleEndScript = NULL; - memset(gTrainerBattleParameter.data, 0, sizeof(gTrainerBattleParameter)); } @@ -1024,7 +993,7 @@ void TrainerBattleLoadArgsSecondTrainer(const u8* data) TRAINER_BATTLE_PARAM.battleScriptRetAddrB = temp->params.battleScriptRetAddrA; } -void TrainerBattleLoadArgs_2(const u8* data) +void TrainerBattleLoadArgs(const u8* data) { InitTrainerBattleVariables(); memcpy(gTrainerBattleParameter.data, data, sizeof(TrainerBattleParameter)); @@ -1216,11 +1185,6 @@ void SetTrainerFacingDirection(void) SetTrainerMovementType(objectEvent, GetTrainerFacingDirectionMovementType(objectEvent->facingDirection)); } -u8 GetTrainerBattleMode(void) -{ - return sTrainerBattleMode; -} - bool8 GetTrainerFlag(void) { if (InBattlePyramid()) @@ -1441,7 +1405,7 @@ const u8 *BattleSetup_GetScriptAddrAfterBattle(void) return EventScript_TestSignpostMsg; } -void BattleSetup_SetScriptAddAfterBattle(const u8* ptr) +void BattleSetup_SetScriptAddrAfterBattle(const u8* ptr) { sTrainerBattleEndScript = (u8*)ptr; } @@ -1483,55 +1447,52 @@ void PlayTrainerEncounterMusic(void) else 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) @@ -1571,7 +1532,7 @@ const u8 *GetTrainerBLoseText(void) const u8 *GetTrainerWonSpeech(void) { - return ReturnEmptyStringIfNull(sTrainerVictorySpeech); + return ReturnEmptyStringIfNull(TRAINER_BATTLE_PARAM.victoryText); } static const u8 *GetTrainerCantBattleSpeech(void) diff --git a/src/scrcmd.c b/src/scrcmd.c index 4fa086e9d4d..02a47b4f088 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1962,7 +1962,7 @@ bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) PtrStack trainerBattleScriptStack; PtrStackInit(&trainerBattleScriptStack); - TrainerBattleLoadArgs_2(ctx->scriptPtr); + TrainerBattleLoadArgs(ctx->scriptPtr); BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr, &trainerBattleScriptStack, FALSE); const u8* ptr; diff --git a/src/script.c b/src/script.c index 1509888a100..7ea35d0039e 100644 --- a/src/script.c +++ b/src/script.c @@ -189,12 +189,6 @@ u32 ScriptPeekWord(struct ScriptContext *ctx) return (((((value3 << 8) + value2) << 8) + value1) << 8) + value0; } -void ScriptConsume(struct ScriptContext *ctx, u8* buffer, u32 n) -{ - for (u32 i = 0; i < n; i++) - buffer[i] = ScriptReadWord(ctx); -} - void LockPlayerFieldControls(void) { sLockFieldControls = TRUE; diff --git a/src/stack.c b/src/stack.c index 2bcba5be050..ee304797e68 100644 --- a/src/stack.c +++ b/src/stack.c @@ -33,4 +33,4 @@ const u8* PtrStackPopU8(PtrStack *s) bool32 PtrStackPushU8(PtrStack *s, const u8* ptr) { return PtrStackPush(s, (void*)ptr); -} \ No newline at end of file +} diff --git a/src/trainer_see.c b/src/trainer_see.c index 24ee878d0b7..6704f3d750b 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -444,7 +444,7 @@ bool8 CheckForTrainersWantingBattle(void) PtrStack trainerBattleScriptStack; PtrStackInit(&trainerBattleScriptStack); - TrainerBattleLoadArgs_2(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); + TrainerBattleLoadArgs(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET); if (gNoOfApproachingTrainers > 1) { gApproachingTrainerId++; From 237aacb5a8ee8a0c121890b6fe65bb288ae2456c Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 04:07:30 +0100 Subject: [PATCH 29/39] temp fix --- src/battle_setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_setup.c b/src/battle_setup.c index 0d15a53956b..d7064544c50 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -81,6 +81,7 @@ static const u8 *GetIntroSpeechOfApproachingTrainer(void); static const u8 *GetTrainerCantBattleSpeech(void); EWRAM_DATA TrainerBattleParameter gTrainerBattleParameter = {0}; +EWRAM_DATA u16 gTrainerBattleOpponent_A = 0; EWRAM_DATA u16 gPartnerTrainerId = 0; EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; From 82d7251b642099165ba3d151e1120f4df64b3f3f Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 04:07:40 +0100 Subject: [PATCH 30/39] correct comments --- asm/macros/battle_frontier/battle_dome.inc | 2 +- asm/macros/battle_frontier/frontier_util.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/asm/macros/battle_frontier/battle_dome.inc b/asm/macros/battle_frontier/battle_dome.inc index 9adbcc54e7e..13f77638102 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/frontier_util.inc b/asm/macros/battle_frontier/frontier_util.inc index e40eccb5e7e..10248b0476d 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 From f0b7bb70eed8c020b651da3ca2eaadda6dab32bf Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 17:48:36 +0100 Subject: [PATCH 31/39] remove last cases of gTrainerBattleOpponent_A --- data/battle_scripts_1.s | 2 +- data/event_scripts.s | 2 +- include/battle_setup.h | 2 -- include/constants/vars.h | 2 +- src/battle_setup.c | 1 - 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 21536f3de46..286e9e27d34 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5642,7 +5642,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 07eafe1c35e..51a9a784110 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -86,7 +86,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/include/battle_setup.h b/include/battle_setup.h index 1135bc3e5ee..ea0f8426359 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -76,8 +76,6 @@ extern const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES]; extern TrainerBattleParameter gTrainerBattleParameter; extern bool16 gHideCancelOptionOnPartySelect; -extern u16 gTrainerBattleOpponent_A; -extern u16 gTrainerBattleOpponent_B; extern u16 gPartnerTrainerId; void BattleSetup_StartWildBattle(void); diff --git a/include/constants/vars.h b/include/constants/vars.h index e79919c329f..81d5a19a474 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/src/battle_setup.c b/src/battle_setup.c index d7064544c50..0d15a53956b 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -81,7 +81,6 @@ static const u8 *GetIntroSpeechOfApproachingTrainer(void); static const u8 *GetTrainerCantBattleSpeech(void); EWRAM_DATA TrainerBattleParameter gTrainerBattleParameter = {0}; -EWRAM_DATA u16 gTrainerBattleOpponent_A = 0; EWRAM_DATA u16 gPartnerTrainerId = 0; EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; From 9753c60c963ce306fae5c8c321280e99eaf409f0 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 17:57:35 +0100 Subject: [PATCH 32/39] rename snippets (again) --- data/scripts/trainer_battle.inc | 24 +++++++++++----------- include/event_scripts.h | 30 +++++++++++++-------------- src/battle_setup.c | 36 ++++++++++++++++----------------- src/trainer_see.c | 2 +- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/data/scripts/trainer_battle.inc b/data/scripts/trainer_battle.inc index dc16a17ae1b..3d31205a508 100644 --- a/data/scripts/trainer_battle.inc +++ b/data/scripts/trainer_battle.inc @@ -129,23 +129,23 @@ Std_MsgboxAutoclose:: release return -EventScript_LockSnippet:: +EventSnippet_Lock:: lock faceplayer setflag FLAG_SAFE_FOLLOWER_MOVEMENT return -EventScript_StartTrainerApproachSnippet:: +EventSnippet_StartTrainerApproach:: selectapproachingtrainer lockfortrainer return -EventScript_TrainerApproachSnippet:: +EventSnippet_TrainerApproach:: special DoTrainerApproach waitstate return -EventScript_RevealTrainerSnippet:: +EventSnippet_RevealTrainer:: applymovement VAR_LAST_TALKED, Movement_RevealTrainer waitmovement 0 clearflag FLAG_SAFE_FOLLOWER_MOVEMENT @@ -156,38 +156,38 @@ EventScript_IsTrainerFlagSet:: goto_if_ne VAR_RESULT, FALSE, EventScript_NoNormalTrainerBattle return -EventScript_PlayTrainerEncounterMusicSnippet:: +EventSnippet_PlayTrainerEncounterMusic:: special PlayTrainerEncounterMusic return -EventScript_SetTrainerFacingDirectionSnippet:: +EventSnippet_SetTrainerFacingDirection:: special SetTrainerFacingDirection return -EventScript_ShowTrainerIntroMsgSnippet:: +EventSnippet_ShowTrainerIntroMsg:: special ShowTrainerIntroSpeech waitmessage waitbuttonpress return -EventScript_PrepareSecondTrainerApproachSnippet:: +EventSnippet_PrepareSecondTrainerApproach:: special PrepareSecondApproachingTrainer return -EventScript_GotoPostBattleScriptSnippet:: +EventSnippet_GotoPostBattleScript:: gotopostbattlescript return -EventScript_DoTrainerBattleSnippet:: +EventSnippet_DoTrainerBattle:: dotrainerbattle return -EventScript_DoRematchTrainerBattleSnippet:: +EventSnippet_DoRematchTrainerBattle:: special BattleSetup_StartRematchBattle waitstate return -EventScript_EndTrainerBattleSnippet:: +EventSnippet_EndTrainerBattle:: gotobeatenscript releaseall end diff --git a/include/event_scripts.h b/include/event_scripts.h index b8b5573f06a..586b97049d6 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -36,23 +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_LockSnippet[]; -extern const u8 EventScript_StartTrainerApproachSnippet[]; -extern const u8 EventScript_TryDoNormalTrainerBattleSnippet[]; -extern const u8 EventScript_RevealTrainerSnippet[]; -extern const u8 EventScript_GetTrainerFlagSnippet[]; -extern const u8 EventScript_PlayTrainerEncounterMusicSnippet[]; -extern const u8 EventScript_SetTrainerFacingDirectionSnippet[]; -extern const u8 EventScript_TrainerApproachSnippet[]; -extern const u8 EventScript_PrepareSecondTrainerApproachSnippet[]; extern const u8 EventScript_ShowTrainerIntroMsg[]; -extern const u8 EventScript_ShowTrainerIntroMsgSnippet[]; -extern const u8 EventScript_GotoPostBattleScriptSnippet[]; -extern const u8 EventScript_DoTrainerBattleSnippet[]; -extern const u8 EventScript_DoRematchTrainerBattleSnippet[]; extern const u8 EventScript_NotEnoughMonsForDoubleBattle[]; -extern const u8 EventScript_EndTrainerBattleSnippet[]; + +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/src/battle_setup.c b/src/battle_setup.c index 0d15a53956b..78d5531cd2c 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1054,35 +1054,35 @@ const u8 *BattleSetup_ConfigureTrainerBattleApproachingTrainer(const u8* data, P { if (TRAINER_BATTLE_PARAM.playMusicA) { - PUSH(EventScript_PlayTrainerEncounterMusicSnippet); + PUSH(EventSnippet_PlayTrainerEncounterMusic); } - PUSH(EventScript_TrainerApproachSnippet); + PUSH(EventSnippet_TrainerApproach); if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); + PUSH(EventSnippet_ShowTrainerIntroMsg); } if (TryPrepareSecondApproachingTrainer2()) { SetMapVarsToTrainerB(); - PUSH(EventScript_PrepareSecondTrainerApproachSnippet); + PUSH(EventSnippet_PrepareSecondTrainerApproach); if (TRAINER_BATTLE_PARAM.playMusicB) { - PUSH(EventScript_PlayTrainerEncounterMusicSnippet); + PUSH(EventSnippet_PlayTrainerEncounterMusic); } - PUSH(EventScript_TrainerApproachSnippet); + PUSH(EventSnippet_TrainerApproach); if (TRAINER_BATTLE_PARAM.introTextB) { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); + PUSH(EventSnippet_ShowTrainerIntroMsg); } } - PUSH(EventScript_DoTrainerBattleSnippet); - PUSH(EventScript_EndTrainerBattleSnippet); + PUSH(EventSnippet_DoTrainerBattle); + PUSH(EventSnippet_EndTrainerBattle); return NULL; } @@ -1096,11 +1096,11 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, } SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why - PUSH(EventScript_LockSnippet); - PUSH(EventScript_RevealTrainerSnippet); + PUSH(EventSnippet_Lock); + PUSH(EventSnippet_RevealTrainer); if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { - PUSH(EventScript_GotoPostBattleScriptSnippet); + PUSH(EventSnippet_GotoPostBattleScript); return NULL; } @@ -1117,26 +1117,26 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, if (TRAINER_BATTLE_PARAM.playMusicA) { - PUSH(EventScript_PlayTrainerEncounterMusicSnippet); + PUSH(EventSnippet_PlayTrainerEncounterMusic); } - PUSH(EventScript_SetTrainerFacingDirectionSnippet); + PUSH(EventSnippet_SetTrainerFacingDirection); if (TRAINER_BATTLE_PARAM.introTextA != NULL) { - PUSH(EventScript_ShowTrainerIntroMsgSnippet); + PUSH(EventSnippet_ShowTrainerIntroMsg); } if (TRAINER_BATTLE_PARAM.isRematch) { - PUSH(EventScript_DoRematchTrainerBattleSnippet); + PUSH(EventSnippet_DoRematchTrainerBattle); } else { - PUSH(EventScript_DoTrainerBattleSnippet); + PUSH(EventSnippet_DoTrainerBattle); } - PUSH(EventScript_EndTrainerBattleSnippet); + PUSH(EventSnippet_EndTrainerBattle); DebugPrintStack(scrStack); diff --git a/src/trainer_see.c b/src/trainer_see.c index 6704f3d750b..e2309a04b24 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -453,7 +453,7 @@ bool8 CheckForTrainersWantingBattle(void) } BattleSetup_ConfigureTrainerBattle(gApproachingTrainers[0].trainerScriptPtr + OPCODE_OFFSET, &trainerBattleScriptStack, TRUE); - ScriptContext_SetupScript(EventScript_StartTrainerApproachSnippet); + ScriptContext_SetupScript(EventSnippet_StartTrainerApproach); ScriptContext_PushFromStack(&trainerBattleScriptStack); LockPlayerFieldControls(); From e431236a9469fc5c7e47e1dd6e92b7fe8a249493 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 20:21:34 +0100 Subject: [PATCH 33/39] merge fixes --- src/battle_message.c | 14 +++++++------- test/text.c | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/battle_message.c b/src/battle_message.c index dc8b2322cbd..4426cdbe683 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2810,7 +2810,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) 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]; @@ -2818,7 +2818,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) @@ -2947,7 +2947,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) 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]; @@ -2955,7 +2955,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) @@ -3058,13 +3058,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; diff --git a/test/text.c b/test/text.c index 781aaaed3ec..92fdf35a483 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; From a400947fa49f7680505ec004124686e41153c3f1 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Fri, 3 Jan 2025 20:47:35 +0100 Subject: [PATCH 34/39] add explanation md --- .../Dynamic Trainer Battle Script Building.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 docs/tutorials/Dynamic Trainer Battle Script Building.md diff --git a/docs/tutorials/Dynamic Trainer Battle Script Building.md b/docs/tutorials/Dynamic Trainer Battle Script Building.md new file mode 100644 index 00000000000..a80cb0ba6e9 --- /dev/null +++ b/docs/tutorials/Dynamic Trainer Battle Script Building.md @@ -0,0 +1,73 @@ +# Contents +1. [Motivation](#motivation) +2. [The What](#the-what) +3. [Scope](#scope) +5. [The How](#the-how) +6. [Using the framework](#using-the-framework) + +# 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 + From 607c0bb9726d923d4f05465b256ca57cb5340056 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 4 Jan 2025 17:20:39 +0100 Subject: [PATCH 35/39] more docs --- ...how_to_dynamic_tainer_battle_framework.md} | 69 +++++++++++++++--- docs/tutorials/script_building_example.gif | Bin 0 -> 419660 bytes 2 files changed, 59 insertions(+), 10 deletions(-) rename docs/tutorials/{Dynamic Trainer Battle Script Building.md => how_to_dynamic_tainer_battle_framework.md} (73%) create mode 100644 docs/tutorials/script_building_example.gif diff --git a/docs/tutorials/Dynamic Trainer Battle Script Building.md b/docs/tutorials/how_to_dynamic_tainer_battle_framework.md similarity index 73% rename from docs/tutorials/Dynamic Trainer Battle Script Building.md rename to docs/tutorials/how_to_dynamic_tainer_battle_framework.md index a80cb0ba6e9..05544bded90 100644 --- a/docs/tutorials/Dynamic Trainer Battle Script Building.md +++ b/docs/tutorials/how_to_dynamic_tainer_battle_framework.md @@ -1,9 +1,15 @@ # Contents -1. [Motivation](#motivation) -2. [The What](#the-what) -3. [Scope](#scope) -5. [The How](#the-how) -6. [Using the framework](#using-the-framework) +- [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: @@ -55,19 +61,62 @@ The [`TrainerBattleParameter`](https://github.com/u8-Salem/pokeemerald/blob/e431 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); - } +{ + 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); } -``` -# Using the framework + 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 0000000000000000000000000000000000000000..9afb0a81cde42660caa0c7c4a4d90c61e6d44173 GIT binary patch literal 419660 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

oT>w;?KWa(c5U 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

WG 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%0Dh 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ℜ zu|IpYCLgUdp`}~}#!cnsu$gh3hep!zLQ&3B38y!#=8jKtWAq-41&7vJ2YX8Wlrgn~ z`I>g2=2ddbUWvZZn2J|jLYu~QnQOqqDldduL+y2yYh#4&_M&tB{u8~|P{!ns-jv$9 zEC!28%duvYlu8}zGlQTX^T6dUH3DRezM!=FP1$NadOCLQM^anBEb0x=opydKcm^=A z%ROii48eTupEV6{OFC!^y=~ieM0OHN?3@Ze$fW6GEUD){TJ67!3YWpXT^{<%$`tc~ z_dW4<%t5H-y|9Rv_V?sD@pa5L%n1^B05?WsBp{QSs9sxYg*d)ntH>etAbj#bbGGLz zX$kQZjRK?C%BY~~ps596b!jdvonmHk zQ!#&*xhL1!KKTjOD99kSMrry{chOBn@rH#i7rxG(q}x2T4vSUJ(ZV+rjw%1sZ%LrX zs~61IGdj9#@3XYDXAnNk*9U!7UdmXV%uAe=j%Lf0kvj3VVQ-i_qpot5+0;K#sq1;R z<}a5#E6e_|@Il%oXIJ}7XAWmsovz6qlE?ZM!J~Gmvr(v&@3So~^Lp~Nku4w0XPdIr z`e%Bo?jxGbm#bFSj>kpzsD}wfmED$2J3eMX<1AYoA*^2bri0)fSbaoW?OvR>R>MLykKva)qB>#EmlN9upS8W(qy|op6=D3(5HJ z*@SgoKxzyYxCJ8zHWflgp4p?dyGuq)3GuUmw~Yjlk>BEvoYlQVpKMn@jBZAiuZn1>V2LdwQuDgRD&*ut2k1Mk#b&+4nE;q|~6^Vjg zGJLz3x&vZ6XJ9)A0=oF+yVmmG&N~WRvIPAD*arUVbUZLL9+p1fBJBv$jhkng)fdtl z+zksf`Z^sCY|zkrkt=Ee>;$+-GXuR|q$h#dipe7W3~X~d2$xZm{swG20)TC7B&vxm zU<_JBi4=eTGBo5@VB6!*!1mFff$b2t%LaM@UuQ=$h(80{n5<^&NQC=EV_!D8egn42 zD1QRm*uGjoV&j4lE`I>q6E%MYwhcxmk#Joh{t9fnZFR37WWNI2nSTbheP4m?@!x=L z2&`^hR+bykKY;Dfe*(4-dj0^mLqmT9wjm4jw}UVU{vEKL3#ShZ0Jb^*17O?!71(z8 zdth4^2;&vl#`qJk&GzqrZTKE|-gP(tur2hrz&7ZkFw7soHk8!g0oy2)0ATwF>Hi|I zjS2fd0=BV9{O8g8-@5Uz&1DW{}9-&`3Y#4*g#aY=is< zz&7MBVEY%a{R`OsUjb}4%ESKu8Q6CGx4?E|&3^;7*}-O}3upcw*luKm|7T#k6=CLI z0ox9L2Daz^6|kNCH^8>z-vHY{0%ZW4%NOQf0o$m*1KW-N4cG?OuK*%~$pZqy1o{tv zZO2%M-+=8C0I=-=d}0Uu9{}4K5RU=~<}U&W0AL%~4){L?wxtjr0l;I0XL9%p?k)6hj zZ4#Ef1v-P?%r4lnJ_7_1jtAe>zHQSI)8qw!Z2!a9)_gU#NB_pyHjnK%|7mPP=mX9F zVQl{Z7~6qe^fUj?*nWZSel@n4x+$%I{%maH0*r0gp5Kk_j6WIMz(7RpR6yrl>z=(? zz(7>(ug10@z}Utacr~_7`Z)f^*nS#=w*VO1hCrDP{p)`i+s*)EdvL%=`>i@}spfw( zwoP6l2Q2}{_Q%24-;C|_?j(S*?e=PHd#w*S{9$b80gP>6nBRy#GL>b+x@hZ-G4H+SAQDY6TDKuv2fJm z{VqL_!|9!;c#~fvJHI|o7z4vBji&?u$=H7UX>5zbjb(o9b@7`#C>u_0pHB69HMW0v z;a&gP*iQM~*pBkjkcI;qiG>?Te>Jw5+GnZY`vAr^MkOw)4)Meb0NHkCWdDb;Z2>M| zjVbWc*cSB$nm&Cswx!?)m*3^2AoElDvg-2#kl$5&%J z{-?1m(6M683WgpJVj8umpT1J?)7UPF@=2^r#b*57*sl4**v`er&jA?Q$Usy?6Wvk1 zO@A2M!}vfmxa`yA{fe7iwzKs&#C|ijVWu`;WIE5*btfl&H@1fW#~%*3(>z}Sx8BW&0UWE(UXe>JuZWe4freG%?lbX#Av zv>Eqc-?xeWs9P1Lqx))Xt8P;J0*r0u;cW6@*_#7R)8WAJkqf0mmKW}RpzeGJ>5=e` zZo!ffzsy5M>O(}sVc5En02|+rr(ytLyYQ#6og-WLk-xA+yRdBB_9XVz*rt-ltgRSp zX&*D2e>Jw70me4VvHowyHp{EAJqj?k-A?z#Uybd-_0!{8gx24TZOnD9-c#q})Bg7H ze%rB)7Zx3do{Lk&nj`E zW~e{&QpsK7;{#p4Agq$cgIxNYkwx#&oy{;jT_WsU(jtDJHNFJOn-`Dv<(hakws|I$ zxTEHH0me4XLUATiB$Gj_{Dl+6fOhp4FRTTCv3;?|CI9V8Qm?@Zp~3#Av8~bJezJL! zIkaGxW8f%o5d}A54qtD(aclE*t)g(N+kPWPdV3+rj=9iFok12DF0*S_m6 zgV|n$e$I@GxwJl7&aQqnw#xy=cHL_I!cSvcYb9aAr&RBz9AIo4%qM-uYnU8ul5I($ zd-(8hABOz^Ft+P|GqxQbYw2E%?THU-%g?@3a_exRkNrA7jqSM&@)rQI{hP7PvY7_@ z3^2CY0mimi$3e!o9o>$dtmk;6=P6vT8JSIN`Gpx2oZH6&AY_3pJo(&xJmFM3gb27$ zB==z?1w&y(1QPB*P6a~|VN61s@l?P3p;!V*O{+Tv5|Ic(Pqfwy{_eWzR_~Y|5 z8T4~u^Yr?oBY)Mb)ju#v)mrRZ0<5|xZ>+FU!uIe(AK+=L9~e}dJ}i=rEz)f^Cmy9Y zXmK$NlqnRdW)0FhnUw+S6N|dB8Y|W7rBq?8)SU@8yS`8nkZQJFS}##6M8k!1yBP)c zdgCmaYhT;0v{=fm^JwMS96IL7_Q~Q{+?>jnk{734zFCPT$4};qS;_m648NWI_NBAY zQ~ex&^c$ZK+e35|dH@ANG0;nSDaFM+O-%mtVLc-9qqgT1|D*6OLYpRaKfUj%v`}bq zCe9^n-Lp0UKo_%&oPVCToUejJ%ohJk4P zh7yr+T|5Q}Y^r|7QP>=m(7x2W@TmN7K?ho?NM&XkS_ph)1?f-3i43%~pC03-{C#%f ziZbjHm4>)?15t+x8o<7nvz(A9F@)0#)=P&LCDy(4!eUk`QX~xTvh;|(c~VqN-t24O z&!Zk?osJ~HFH@||gRN0kl4C=kmlOkGYm)uE#yTy_l1D8GSKMAU>W4vXGYcn4*+Z%? zmW4*FA4KP;emNRoxzaj`TB>o8_{64;7@XD6m%cx4E}IcPcO#k7s}ic^(B(X`WK=EF zv~127i=hdY7BrxNXw{L#qf?FsS0B2FpPZ*!E`mY&7BcH(?gyHz+jNs42&abMr?a>n zB5zX0^~mj0OhZdhjFYVz995++XvR*bZF?2r~FrVEc10 zk4?)#QQOxRjd5R|w%dKcMfwGT*RE$qmw~6wnJgFg&%kzZyTcg65U=9|#{r%L2om8M z@#)~^rwnJ=KLOi(E-R+R9WHCOLwvVOZ7UpC?Zt08B}+n&x;|7uE)z3#BR?c(A>?(C2+$*0I;1x_*DB%r_1|Z zCFBEOI=(vl35qe~+mYmllCjaFx_E&L2{NC>6TMTc;VwwY8vlm1C2(Lf9$*y4mk*Uj zTOe$19Tk!1Ze*<6$9cW2(7jbb_4VPV?5RA!JBVI$pxdA#oSo=`j6sc_A5Z)_+ulst zxqyrdT-gkF;!(>}tIQg_I63zq4I+l0ln{gDm<>P?Gy1Dt?Vt}p4I)X#Me2d&gUnzF zv!~Zah-yQkB$;*Ng(C$KM{eWOsEhEKC`4t?7##y0bz|kx2h-pc;8!*e^ODcT1+l&- zc~dHa&h8Lm7fEtxB`$`+eI5^+nMYV#A_U2;kVvL%gi{MOpyixQ1btAD2sHLAK}A5=_AMreB^OgCDSR=7^gAYneD$jq2N`jYsD85Vm& zXJ^XUKJ8m35xet|tnpXI#|A9ur0>V^FS`W5ZlJOJhD8 zfvrf0uk-<`wI7t8A@6PfdsX9*QEb_ygcZv&)d5MKFq@iSN3?zQg;rG{54K9HAWQ9$ z167C7g(_EgqC;MBmG+y344=JRT@_6gH5`Vr@1FT*2oJK|1jtVAG-fZTw-W7jHb_CO z2_*uUYs+)MEOkK}w7NoV3xv@aHTc4oIzKQ+SvKdQaA=KSi&G`3bseL$y^J8#j#k~` zkw2Zb7n(nLEKYq@j){jmB%+WQ6W~T}=}`Ilu2f>y=jNhrva(2_99O%-f!&!6@AM%V zT9VR1u>yoWpe8GDLF^R z`@Y*+8sC}_y1dYL+_=j0SC}1=&y>&o79MopcDjBlQ9c*LJykzI)=#iid1IHAAs?!W z)$h%`pbcS504sH}srX&4;T*?L$4#m4QlNeHyZccCsQ-cT+st$NI z1MH2XqFE)y@&mJZsyFqeSH~Kk&6zN`U7AcgirFQ=I2i8}tNe_t!{Z(#_vx4LLbI%0 za6RXzTyE-8CYVhFG!-tsMvs+r94pGSZPcnZmJtw_;figGE*Z|SvF6&_(R>`;=GVCG zBC9I*SRy6@`qx|OOTSawhLiJxm*&ZRAvv-0+(yH%_tK@`sBIN~>VHt%;Y_4Of1$Q5 zN6vRmUmLstYMW~RmD(Pdck63_KoF0$12lNWspmLe8@%C0|Ej^u1ZeOI8xBp<67rk; znc7y2d~NW~0H|%%!ao|kZ+@e;P39)$a)ln^YX64Xe)BifwjK{669X@A}k^K z$P?4>(E?S@%Vy@v&jDy*b;A3(d#KqzsBPPSYVd~qgWA3e2HZv z_AxLX`v!{$u$68o&M&-dpkJD_q!>YugW`wyZGqDWOrizr4{!VC)!POi0eIWUBP20m z2+*Vn(D#daald=p4I@G0I?d41Dkx5cNd~&CMX8j!rA6s6Nu@JsCN@w;CWl9qeMu)e zRG?Xoy`%td8+j!WOBZ+*;B7x)m*j>Kw^HVrQQ=S)1Xr4uri;I+m7vQY0^Cc*ecg{r z3Zh@V?M98`blU~@)d=s=7c^k`hzc>9=!Kp#qkvclvHXu-b9=8Waue3YT#gcE$?EO zGpOF7Sbphf-D~^e4aBhbt#bf6GASC4*CJI@D5qhzwAq{HA7QLOe_=IKdX7P>;Z{x6U$2ced_0O>ZKF*4EOQ+ThOB zInXfsmEQZRT%HF%VMeNWk7W2Q#36v%Mx`VJP}?%=md0Wdmp(dcq`kPrnQHZKh_OIE zz4@Ls^j{6$ta_O$)uNO35X`J*uLvcbySW&>jooD<8ZP&EMNJ<7wT;=vwg1-Vk?TNG z^>z?YyM51bOk10MZ(Q8vvI`>~CtI-zZ`f-QVyw`G+=u+7AB)f9a^VYe@QTLFC*Yfh0yfwjcf7 z#h`xgsnb==+lt>`mWm-|_b_Aq`1_x|d>9aK_b~8Y7QR=f=)+AF0(=hASi{k~q@Rx66|Gi$^Za zIm7bl49v$w7PcVY9>Oqw6q9H)6QS)FMqv#45%50Vm~L1*Q8_s*z<|EY1|DqJ#Kx^t z*hI<2%MlMb$c@c`{48XDew@>DIX>ZuId#FxB>pQW?#5QIJb&Ik<3Y;{?pF6;)_o$y zl@s}(O;ufP#ah<6cAY%7WUQ-*C8hA5Qt<*1Do}U(AwRHFE`}NDdMZB^^A9>|` z6C3_2nnR9HTy3Q;i01Id6n%B03otG!Vp?s7;xuX{Vx?pi()gD9quizS(J~beR@n$> zsY0bYj2}1h-v~~H%2tN6g!*I|>p`}4R(2#fFi0)JKwfqAsoH#iuw2ZA!&PgUw5d)B zDm{T1YT$5DO=-Eb;u68toE{BqD2__!L4K%f5N0=cwkS4O!ol@_QTW#QtVO5M0x7%r zhS3ZB>5Le8SyBS$wt0A=l(h{76~w2)_&(vxA%llGwzQ&U%-UMoXKYmErpZO7oNUpF zYm3Y^d%z{Kqj3$`6zOvHcIU;Pz34%3iWU?^)3psJ=Xe%)_eT@(p ztpO<6hNEgw%iVmHA9jfTNEAY?%*dD!`}lU7cC^z?K-kuoMGidThFr=;TGB}7nG0U! zJjSZg%e+e-Y_*ud9?x2^fJBkAHw>g3&<^2lnH{^>(`4%^I;T#9I_)TK-J2T*?lzKp z>4u-O8~kdVfX(FSqUSo-q&Ox|q_RwLsyEdk(*| zmvd3rWEW=}C(pBAWrjs(SNP%E6fs5F2Ewn{&aSI+mzCy~6$>gNWkb0OB_Pf)wQr-c zn^zttdxQ8@oV!<`g|d1JT;dGT$+_34$21l(*#HUd46laJazjcBD`RlZC5jM*F1|k8 z`*Tsl)|E;d-?g>%N7clSA5>Qh!F@}~d^h)5q2?G;ZZ)Aw-0g&Yw@gr5MYM?HQScP# z@A|pEvzm?{@CXXYi`%mhEc-ox`#*oOB@cCCQqrl7^MB*$uSPC|%))f#%*4=4$#(Pp zovRelt>l*lhvtTWgN1-^Yz`VmdY5F}dXDT`XaE99mz&xDiOioJHAsYsl@N+`Gf7t1 z)v0zdNWs+U`=tTaqBlU^zDe+gBsa8E`rs4r;d}81vKtQD;ox#1TaYGfI#q1z6dunK zdCMh6VH4h2Aps&IK8A!4w_8T;*!N~30m?7v-sns3(Nnnf$lu1Rg>fZ?#krzgv6!^5 zvCAV1R2T85G<$vDSM=QTsDL!By;X$W^VCW*V<(HK#WEqAf5#Lk=FcuzZ|0fSBw4Da z;;L$u66CFa7o;5;scRNlhhZhzk1IWIA;%hy7ZP0LhHdJ~zhY);d=Sc^?9zf}15O!@ z7%KW1Bih6%dV0{td0x!r3dfIJyr~v&1o03!h~hkSgxvFgT#nJd7DN$~czR=(5y(qV z8HST$b!Qe*X&OSy5%~5lmKZZmkTdQLWMGG|1S5qES+RrOn>eg6wi_&CQjPc+R3GT3 z$fZy5JD(zThNK&koCbU1sYXP44rL5pmcqx1+*~mfJ{*R)VO1~rh zHX$`xRjZBW@MSZr&D5xGw;#TQM(-c`W|xW{bEaFP`C+^H0;6idFQ=Km4>xIv^_EB; zIE-n~$Y6}qsovMVHD;z4x4OO2+W-yg`r!pX0%0Wpl_&sh^;6*p~*u zhKd3X!vLWv=bLZF~)-7}nI(Lp$ zw>*0jdp;+j{`SW(s6-*EL^#yYnR-413$wt?r4!5Et6G0~B2s4Xt_;i8pyA+=m6pyAtxAfwnuuNG2%6<^aszuok z$HEXoQT}O>pcbeLDAcDffx->RdaUjxHU6eaBT?AJX?$ud?yaSo>6ybVC~L`LYx&l# zl;XRo(YX>a^nPHO(`A|6B|D0OS@YwMUQ99&`^xIOp`9sL4pZISngA?X2-l)vC|?EPS#uDcnJ6GP zU@r%EBG+q>8YY4=9&NL>nM^tu%r>&MWBp++NQ>&rE zZPd2N3Y2%xO7O)@wrE!{R$FoH77ll}uO&4Esn-V)@O*22?Vk2MDFKox%r&IHM9AJF z&8-PV6uD8c%~H9%Dth++&~=XQb;j?WjqM$)v6IHOZQHhO+je$r+qR7+X{-hf+hk9F z=bV{q=EeLE&x`N%tb2WyX3u74H*7Ulh2Y()S2G%-kaL%iGO?gBM50`Wg`9yLmjAR> zmc0*VZB}f3Rda$F}|ZRey7!tQG&`Dk_=bRev6aZFrS6hUvao?_xPT8(pW z=XF=74A1qZE*wHJ(ocW*?yO|#zTS`MRW9y-ZZ~{fepQSf$W;$v6j51CMFhqi>^}xC0iVHKjgiJhh!7wY9Vr5HjtyhZh&UVX#jfc*x8Vhv z(`HhPi5srV9%NeqBxAkzl@ev_~r*D+je`M#9iAcWz zJ}>{R9AnL6b+)LxLJ9xC#+U68o&Az z-UL()DJI`QZ};!Jh-T}cpjV3qH`5`?CHO|CVmLd3pfbKv0$E@(Zoof9THH)%+lo1! z9s`P>V!|%|I=P*rX+Jk5E zgl87#z_Mnk9k(;BuPTDEEBgMjcGx!n<=`sN5;WNpj*+TXFDk3BtD@imNX~OJ|JCK5 z&Y#P7g;~*`z_6PzCoE2lU0BhsDzTfL-)(_%cX;&Xe5jIo!mZhwAUL%i;9Xky#qR)5 zx;U*r1#Vq?-n)#yzic_SR8cdr&kwC#(^P!oL_=g`oVx-IpFkf_7n;XH=?p^&`WNPQ zh6z)KU~+}wpI_yen?WU9D|lUj=wv2WSmC{@UNm4u^h=Qg?^KcgJ?Jlr=BCXLzfJs-R*vBR;a7l6@DFJW_YIBSV{!|CUyR7G@58 zkA!(k|9YmrFJ__uPjeRdFPqJII1xUi8ImUuJnI*uv7b&x{TK$-jJ6X30;`o$AvI$@ z`1jWsUvz%+Z|0@LyiHBO7LnM(e*ThA&+KtPEx~rmdNv|pf_`|v`Fi)1;^0K!;LKs` z1F0{{U@Q6Z;AK95<8aS!r=ld%OgGjJHB~%D5&RSjsgZu;`PYj#e;fbMkbV zKNWK#-;i&QHX^&FqG~uIoz0`BSolL`<3<$6^YC<}AIER_R78J6&ESj%$yLKKk^}9? z(Dq~$p+NrNWVyPjkoQMf>zH|$rq(r!#nyS#agh??h4tStckp^c&=+CU*QsfIBs^1g zD3eL}-57@Fm?iEiX%-(EE`FL{>f*XsiLW`YsUgQNGmhgg>{I!wECJx9{DOx0g6Au19p?hr?IK2_?f4v6oNset z;Njl{V)S44*h&v1N@lP{wlD6X_tr}Y2}^XpSQ!=_m{4oVK|2n>+@-QufX@*Gj$bpA zGY+KpFRW0j*zJC!KbiA`OGSSW)%K|AcHx{T+6z9VL8laL3eP`^eAbK5@|MuhOg%X{n1^o)!z5p| zWGohCDr`UEeTFolKtdPDZhrA|Duq<05Yr69LMDa&8-9FOGTDE4Y3#5_tMOb6ga@~J z_oLNJCXEe7cpLNOa+y;qzP@ggS)9kEj;oi+C=eqjb zX2+0O1VvY9zQ`xqK}M5>27i8Cu9xwhU-g^Z-_NCKQP@YLk#16~mVu<1-`0-Qu#O9q z3c5e1pThq9a;m}q0^AF}L#?3>|2c$=9ZoqQU}%CNcW*2$m3O-zc|#Fx8UTlE`!4=< zPp>?NYNwrq@iL~}n4t+*5{`krNj}3xWIdxK(%>noJUPwXhC1}^6R^@nh?tJRM3CWM zKS8ybiYEK&e1kqsipY>ULsDNij47)x{~*V#VJ{&e3gnMz&5xa(=Dmj@bXJ&jKDOtc z?GT?+T)gpfQ{dTO16O#33P@gRLy|xRsa&Ex0Ti#NX zYe0`XFJoGXd_Hbl4aT!UJ0LW{mvSV+JvI7tR0e|Q@k1& z*`n1Y`bsigDh{@kd)quNIPg{$$4K^othWsH>X{MR9h2;kzU6-u*FY0qTvje%E#J6{o%mRV zB1i68rDKesUpkRLdRqH~u3z`up46s(0l!dKoqB)zd+`0^rGLqLZZmW4P@#X}+z-Gi z(RJZ^2xeR1ZiDT^Q+IGul;Q`zfs?MGPyYG6=AzyIT!{Vj;#dF!{CwF^(fWklAcFE8 zX$W(2ctZ*i3bZ?xtIYG-3dl0p-Sev<@{+EZ40&28w-EciRG=-#v*|af>VK|<+H!+N zPOi)gv5kse`M&Tf@QF}hjtuJjP3;7zKkXFzxWxAF&rQg4>z?D(J5 zHn$Y-#&V+9*#8*3EQx5sX7~{_SXMbK$u-#$WLW=F+ng&YN#W)clsq!B|Ht5+maZX7 z4mFo11&@&wcU?)Z6t|$$=$6&2SV^_@_s;7GB(45vw*p!xA_CP ztVk6+?j8ZR_7?1wJTl&NErm<@=agmLi~f;pX+IgxIf<$jJzvvT9(~tqFSjXF}T)riI5F6z)0EsBJb6bWXddxdOkD6BhYC@!73r^r?wi5U9p8o zZvx6&DG?xUc<_4GMUUH9;UH>GH+W$GLSj_BzEbfx_H1afsJC~x-p$h7XiRUvkX4FX z2&v)hSPZDwlR(_P=*Vnrg=TV{r_*xs+-z8LsCRDFQ+gEiss##ExEk2*?b2nIKHAgs zZ^r61AhZ|!hOTyhk1+~+(QNxS>J#KOWAt(0)$*s^${b7Qa5)jXe`4&ym1}3oXJw-v z+|nWNsaLUC_pO8Y%h^ze{un7qdknF{Ay};L2*c=Yl!5ah?g;-UW-Z5fXTU>PT(x0c z4`4VLnw1(oSCtrNqksj)HI)(6Z4zYqyGByeHNBj0fvn7PMr(qVwRUcg!E1Z=7?XjA zGJpNMpU$L(CeUV+V4CeGU`masT0Ac9OwQ3~gs`27F6U-3*3os8!htP!eb0>RJZB+7 zvnn6bz%p2HdxrA#Mzvp0otqD<5W&&bf!5&?XsA2POW9yWl(+Tv^|F-V{+O$hztNMK zv7Y|SWH`BFJ3r7rELTx(`J5zefRe?fgBp^E;wHgfYtd z`JL!tjD=9s#IO4(DexpgYtIz(7v2P?Crh;0-Xnq)?j+M;9IsH>qj8SL$S z@%7^{?swl#6WTLV>ix{$k-)ivyMK?x+*!5BkMv1+^6$`33p%iT$r-d$;aK+3q0eSJ z>;G-=Iw|!^Mrps;#4O)=P5K=?4|u_`FNOHS`X53IdH01m3hcO%9GAEAjI$-X{d*%r zk<;{W)R6|!KMPM^e%(oj7b!rl zT4V)RZtYLShKbw@t*XDqW&Kc_tvD^$xl^1%!`2ozJ9j3Vi*^B5kNsTE4K ztjML$HELC={hs3p8@8)J%fZBQn|qqH4n{00mt!cPObZ*94t*y)O8$2ULK>(JWa#!AE?G-x-8F%v#4Iq z)SbXAjIr{?8B0B3#DlW1!N=0{N741b0vIgwnCtooT3dy=edJ*4YQoQ~85>buovL6o zH!GJRs#IS9(-nLE;pqsS%Phxnot$WL$%$|zArle9Y9>xtx)^9jlge6%5zu*!MicA$ zRqdaBS-XaoV_73PqXD2zDkr7Mjobv4N;*&uVV1VZkhj-5G8>}}w{5=RcU=`bBO<<{ zzZQT_w90ny*cG~MmvtJ>BnDnZ|?oEs3}P%fB}B#=-;t4T&G!6ZZ@Xr{W@=y4{CIe z6@K*NI?l8GU|{Rw{Q=cF#qT#;l=6xHZWPG2BT2p@F4XsXsjoniWDT&`>24vHoFCD2 zXwly;eP}c9fo<4`(}Autig#5>U!Txg>D0@}w&yl$0N7{Rmu6oU@K;QD2X{$P&PNs;F``Id-$q~!&+zjs3mTa!DQq@Q@8ad06{BV{ zoQ&MSdQM`bL?T8Qy%wv$+yfiu1un8SMdb&I`Y2fcy*1Mj$pc9GQG`s>Q7p9tuQUCv z+Oc^lhBEvZzWj}mE;iO#@MAIFFzp*WF`Q=AuxT>Vx$vfsN@(AMc0h}?WOmzPv{-l% zC|tTDV*4S{d(KRr(7lW$7Mjxt2?*r}#Nzx)k;IS(*1~O1z9HQ!-~!7i&b5T{n;ETz z|KwD;Vvl6q&ZXw|nbU~87sF&cikPX$Y0G!>s<*Ia=;)Nwt5oyChDZex*kVve9W`nM`B)FZ_U+dj*)k_)7N;`?C!{Dko`?3 zZw6cs+@=@xZKpEY#cKR!vse>~Tq<3?I>5t$!E?Wqx+83oo}#B`Vu4Zh&bw^ZkAoYn=GTaW8_jb*WS1owNX>#@D}LhB=o0Po zjMi?H@N?m%)g^y-QNGQd6Wj)7`VoD7&u1n~yVkf-hH1c#T8a|*9l7QTNf|41DZRo? z>_M4S%lxHJCy;6TJsFMgB&k1o=hBk^`87%z+0cV_B@D`#6D*(^mB~`WWt0 z{qtPVqk1JGM$Mh3_9-Dp%7W7}+f02n2Z9Aep<_(d>khn}{lmd}V@~$2{N(Y*COo zottM_cXwxSbNDMK7mCqY7;o3HdnKbYvBH2PJKI?q>agYLN?Dn2(If&PWd78giyF%L z7YcvDmjG*kIgnAKd}co|4kmBKecryMI`4aJcR>*S=~0Cl?ij8m3(0oH2!Z>oO>5G+ z&I?-!ha>-N3fm9~XfFrGojvfw&h!pcaz4GN^TTuJN#tE0&>I(ZlQpU)eV|_-pO)AC z@1XtsCgC9BTa7ZV3VWqE>n{`=HUY#zb}kGK-N>DO+$0nz;KWZKrc;BZL&nZ)NDcZY z|2;Eer>F}41hgG^>Ak8N=j9Rsp8za(i36Ug0-jX&)zF^2Xx^<^`XRTuJX zA1jSq?DB6K+Fl%A9zpe`6&6N2;~a3>S&f=eE!Tdx1KRnNPysW_oUCUAUK>kN1=g!s zxtC%LALY=uhN_{o;nCY|KOXo&@piQiZgDMp`SA|#t3h`v2%ENQJ4G;U<-~X<=06QW2I?WOS#hDxAV^OOpL*eO41C~IqN}-oq2IVdk8%I4EL(C$DTy9` z0}K6jW*u6z8GCHy^hg;Y?Hw)@9r4;lv})!dY{D+JNzQTX{zl`fcwxJosVPGlY^fTd zeUZ!qmr`P(Bvh^@qN=91oUEmd7d8=PeIZB$pZe|H3hB~fb1RCluzBIWeUhHcUz5f*xB8p2R(M(NM|@jeK=GZJnythk;2-YZ^g15 z()fJKjJ(^6G$(E0Oz=C4RaFj+lCYJab3V;OK=Uv@ai+l{o~eMg`-V<|ur;^nl--2MSZjCc!c@Fu3WLm&s1IkE*q^qM{8lsaQwR2f7^nHQ( zV8PI7M-CPuj`ls+Bhgu&Hf&s1P};VHx^!fh9hHA5E4$!;hcp$T_;yyZRyI3;B}{_W zW`bo?=JzO=%pc)2LVY z#edQW3peh9gUwu`c|_J@(t6?R6fvAv*JbJ(OEoFrMyzYr&Bio*pQi8Zq#snxiOkCR zeMN&k3)81rdSX%khgXx$A{>J+tz^}UM<$F-yJBeD#i7*~!LMp+N2|TFE_^(luhfqn zRKxbH+l)iN%FJRV*VO#+5g-#2&DE<(`NV-O?TZ`ThR@Aek<~_^?F;hKIlBb(wz8~w zwKus1Y-P1#_i|mLL!mTd3hy?rRA;E`vi;2pvgd36>g;fg3$U)KNTdo<0R#akIs821 z{P464|8!0_OWA^n=pUiA`Z@&g#rwo`#qw3&RAx11F}v*o4kQ$iq&1~Ra@0!UEcmvv+xyo)47VIjaDw+JYr0c2$oK8 zb9s2d-gVf8U%|N@fWWgqB}VGJrovjp{BfJxP}@8ht0=?L{6!~#_nHQil$Z=16IZTL zm?Xsswh6U6dt^)mTBE8dD!l5qUG+=ysvD5e4}#Lg|OT%!A5Ta9J0LQr2)WSBLFVv zu%mYTG9l20H55G(V^`*pTds$|=D986uSNW7XF zOsV?Bm}W!*OsI}{qfe-aH2PDNWXzS&@dwYtP1|7hx=GgDRMo^wkx+TD&~DDandWKm zjscFK^gf(~Nyg0?W@mQ$NWJr>^YEKgU0<7B@8zr@RXX`cRD>{+=j{FFY_%8YCPe(n zT4C!K(vqO72X^fTtg`BIY9~_T<{Y-Eap5PgKB!w(8_wqnXv@)5&=xNroFtSNC7NdW zDu&Rfhv4@HH%1q1s7KRx>CyDKbv2f1>zLpYdiFF%!1x!xFJr#gFPh(U%X;LH{GG-# zFoh!09CV$V;2rHe*ZRY{!ov5x>-D>oJf3MCo6Hgk0GYHCNlOCMJI0wX#+880EZ2G* z&wO29D1Vci>`L6pFlm^TLXz5lS zqqqaZy06r_!;$G4{S5Nua@<17?E(ms9A+tXw(otH;kveV%eTctw(|aIE~5kVQ@tI0 zJ56aUoqjt#t;CD;rge;Yp!N*`^zDv4Kn_x9%0uYfbzc*5UVVQ?m)dtj_?;rQlpVc( zaqs@AefAlFy<5Zr(DUBfHb#m=Nfy%Pe$D)L!N7K9|1S{z{;pmBnOL%&+QAR`!9TMN z7yG3wEeF=@=4gb{_m>AxHq#ppC2;(nf9rnSBa1xl|1g>weAOGgHap-lJCsm~V)l2% z+Z#q|IAn8=a(Wy=KPcWQ8)nfr6*ewet%+hlnxU0BLh>a+xjLjE7Nfc&Se6>KG9Oh5 z8&xrrOg=lNM<`R&|H+Kv!(f8J1C7y8ImS(NqP8~ndaNLRSIQvxlgHn2L({RmYFyfD zT;&cJw#JKEH!kLVYSSl3)!dD`g4Th*juxAx;@fg}mhX9;zwpuR8Ki1Da=oM$d-v71SXX-Y z+#q~w`0LleT^{iaG66m6^)gKT5<<~ZB5WFL5DhwGLP6a{4AV@Z{T1x~J;vyL63)Z1 z{TO>cgWR?jtK4_0q!o(&IjZ?px}X(&6ex6%0=_U)ItSwkB}j|MXoaufaan4upqxcC zVMnS!u!U`1qM==);J4{rj6_g?lG3_x(pnQeSv3BISHWK3c2@W(JIledsl$fhV7nGz z(*ya!YOzaaaZfL4)A-kmTv{pPGJwpaU31qU_Q@ctmpkC+cFy%{RKe@{b1-qkC3e7D z?)$5cQ+NDka84eydtNDd2~d{KxO1f{@k3=A6@gt2u zkq$?r@erG1sGdlZleU`U<*=H|P*H1Cm|s4YPi50sHL%;Lm5C+^`?6w6FOi5wAW@rQ z@-|mV#8VdtM)+dHsWWI;W&Va&A(bc;6tlFjX1CW&fFi>0msm@7C+h zBiP40S<2)wG@e-;zfv0Y2mLuf;@7I(YJk`*3?Rs=SL$@6R!X45x>8@zXr9xTPPQ{h zDv{Xa(9LDi@2vY}YeBSIyuBn2!uy7lp#AE2&>v7)C&26Bumxkm#dP4?u~?H+X4>!} z&I<+>(VER`!X1>kyWR}r za*BH-gJ6z+LU6z9t}HBeqk&x(20N1=7BM5s>}0CDl2TIJ!O_Gi zmLYMKbCSi5lH~5SkON@pT^pGj@d5G$nhdGa6#a9mGci^6PqKyht~ETkcVlcy0hd;Kx%c=LT7IL$-_W>gU>xcyQk3og z6kiDr4Gk@eb`33~2o6mhg@_V0rC&g{I6j8}6HTKaXijaDC`wIjLl@{{paCCahmKWI z#J^&kLqC9wA@fvS*P-*YL(gfw7(3Fu`Sw}QZBc^DKz)>`Q`2&tF{6j!u)OoYcobPw z%d54WOWo%WH20y#s6))2+Bc|Yk?{6;(<4ie#=40LrDVpjM)jz-VTc~3wvis{hPFvU zd4RLIsT}9~TH3J!p1HP?sE=79Uq72sn1X@!iG!BshN*UdrH*E?1!u;--76!PH3#Mb z_fZf_Cil5dUgi$yM%#kW{bXdj{YmbNLH-j#E)c33S z+5w%CCT-yakrOuz7>z2CD-C8jHFPl=R z0`Hpzsegaf>Sf})7T^RPyd43w1f4i)zGWOw*q~oe@}eHRLs^%MLKj;{qot#|$>5tAE?PUc zq}p?n;TtbL?)1OWY1i6VTYEFYQ|US`TgU$(>pFj{asC;X*Z`Bj8onn*D-b7E*4sd9_dgu=Ql(jTx>>gWs!`E3T*LoaPt1q;5` zCz@3#zcBEXC%%(8Iua-%+7lqc~KWt{}#577Oo@~iK2#r=q za{8|OQ7vf84tV}8)W3hOcwqB?6AghMTvAvmEFB?a`LVs=v#=6~#Yij(s+5l`MfFDa zKZO0JE9)0E!E4@VR^PEgTM%n(onr{ODvxS*cTtA9C22s^_gnV!V7b~IyrAvFStdejsiX(|0BVvA~x=$@m3~?Cw+;&d&jYrk`6TL#8F+=kiUek)FEnb3>UR+}; zye6By-sx7WE7wg{ePq4io);U5IW3}$^j6IanxW^fZ)LyiscMvjy(w0&_QVwjn}dV> zu{kB5&J39*@4Sq1602V2h$VLG;&65t{_k+?_Ax3Cgxh3X;Lg7rA!!j^Mw{l7@}$FY z8rTPTf-Pmri1ZHmKkxPaBqzFyLz(Sjp}Dq3vpXj!m#ujvGj1ibT8k8Lyz9`n))DNw zLu0U1sx}R-IlcO)1DY%*M>7Uw;^@avBAu9*cd^I2rK4?d9m^tjuFrY8CyG*SWdRVL zd~yais+&^KnM@%be*Ve)Q_<{^E)HHUxL54MB-(rT$# zFbeq<9G0QtuVvc{F_!<6*wX2%c#`g|NByvOhKv0vHHWtc2!AdRPwfh z1ASXuad3gCm)&Wn;}yXZ4=)Y|*)^?*hj^!1_IR{l6!SRK`8+jYSF)0LzeRcOzzhKd z{tX}({Y0@CWqlXmZ?UFdOP9gg&be0pcxpCZz#+8q`HFS)E#P%H>PG;Stjexz%KLaK zjIIQ32@H$IT0s~xid8B$q31=343Z%(kRuEEXfvpii2OW_e zAFH#58lb!~iJC0?F`AKJSz}W{QZ9~`lgG=u6H}J?rV1z6>|$8Mq_~Muz)1?akSuJ) z=KfKqzFw1F*Y+`K*D!Ffa~%*C@xFqeI3a$C`kj#vvqF(L@1}I3;iO8Y&@jCqdnIza zFlI3prorN>z}K)VHGzO!wY{R^Fj1;QZ?{)uLNBAY=aJ@n@BK{Y_kQ0In)@NBs7WX= zdGoySVR_7drYc&|R8dMbR@eDhw?brOg=TBLWZhk<05t`V6DY+*qajflk?nJTKa`JiV3Z;6B~T8%!4IMp zrR*Ar&s2D`x_p;wfKrC^+z)-k|H4N3>jqR7mslBwDRvMn#GUb2-`Kl;g#=dS2>cWQmvQ(}<)CoY>| z@O6=5)jgvX7*l5Of&n*%gs2-yTT+SJ3OA6RyaVGcAgapdyHR&`e&4~hlR+1CFm{A8 zIxSYxJT298Ldl+zL(bhZ5k0uQ8ee!h>$zjeRVzX*u>B4q&$37f1|b;>%URLw4L20S z@mnt-%`DAiTV{c6QHozr4}-ffa{)4}#kX}-pbXdx2pX1~09qRA72+j?F!%`U<#n+*h+jTtQgG za{m!=FN=p%4~L3SOg81P)xA9|D)e0UMNonR(>D>;tJ)~9Q7*P8t<)cXop)K$$QQsY z`dsPmB1b^f9^0waiFl<)`iQE)Jw4ZH){#wT^^CJfKV4bVW}oSqX)#K-x8U&8(edP{ zy)MNW@LWq>4CQD8&1l)Y`tIx+pnHU}Q`jq634lO&O(|XT^^Qtwb8zG4fySfSe>Hb^ ze;{m{k7ii8IFL=La=rqAdPJ*^GIE-wu9=&+I-W_I1~;~xnYDlM*Xk;o;-hhb^21{0 z^d(zW=sbMoE$sb&{8{Wd^N4gCZ&Ys+-5Y(^>}KsV;Ym5`ng*X{LX~L>y;MCMXi@67 z;LF=Xiy1Fl!R}cjh!x#kUE1Jiqc@)YaRXFst|h4-Wi~yyE5u2??!pBdwKIGwlLKOv=xh63{{ zB>9soXNf)V9AV$@%+YPL(2LULoJfVL7VS-suJj=(f!S>Ej0m6*RJ4sNWsS;pKBaP= zTGWj+#Sr-<>g++A#65T*LDdmxbKz{QmH$~E7pi0UB$b56e?OI+q9cek$Ts_EO8z`w|7<&i~@T>_;V z4hQK#x4BDkzW}5ux!3;~*-39%Z^rJ-k-ZM|>S?%X@XVo=Z)plYGK-n<97deYIdLr- zYfFs7gA9(VWy>8XH^n-CaUh=6U0wkZcxf5O5@48-Bp2;hrHUt*l(`nu}cfLN+RDNr&t(`iqRRkDi-%o$OlUBaD2W=wD?yp)IoT z_Y)D8yuoj~4m*QdaC>b|Wd- zTRT+F9557jch)qyx=I`zMOEHG<{A6f=I6eDrCM>E!73VmJkU#9Q4Ct?>@Fx5g_Ccy zID8rjIWPH4T7Icx(gT9Qx(p#{0#7r83p82D%qZ%HgGb7P#XIyFhnW#ZnE_k!)G&VA zWd^X5s#vh0YaA|cT5<@J2378cCOM9*9^T zrf?n*Wu^;1gQwI?pIWrdxS2(b%@kn$xL|yKtvj_!D!Z|oQ$l!qX?cCeqE8(ay0R3K zoZ$AWifX{}vD^?y-wculO-4{^31&%YsI8lqO2v>gmW4J+6+L(bSk}?oduGsd?DuMIaOi9$vO|U*Rr`ll@A;;W_nJG>wzvb9hWYW#? zF|4D&C(RD61;91@I?|mfXhL7!LY}QdU%Qg(PFyC_<B58vbyW&mQgK}4uEFS{Ppo4lcv&W`_cx0mX zrqb8N6Z5xoX39en-Sv@a_~CIapSmLGB663-lB#2%wTEEBh2gZ7aqJIs`HynD;PYB^ zaI}Ttlv9&fq+Q6Xl3@NJWgJ5Nya6CRAQ(L9!}hf@MPxyho=7J?sT!oC*WI(dF% zR!){SlDYJS=|1YyK-Fp?3JUAXcB-tYAfR_9P~Fg-0&l}3EnKrGVaUNMt)7? zW~B7$Jrf@uFzZUoeqz(hR_*{F7r7DVg`X67sr_|Q9*6*JhR++_h?($Y7^9LxsmeAB z&yE0HVh9=IMuJzeq9+8WCxqh_DPBe&WamV}Kn8tOYhvd$cROBXJDzFQbcvP~UJ@nk zz=e_EgppL!;>$cnmY!JZ)!4Y_`s6OBu`1lx4&m30@YW6CmzMI1nx-ghp5>rh$$}2C z>Py_TL-*L`i*=cO-;<(i?TYnLzdBi62nl(r+ce^9(Y~Drqw4X|?15;fq9>I~C6lIw z0bzv(k-kjEtf|Wo<7rf0(ZEsC)#L8{;W=#G;%%$<)3%9$9=JITCjH^CW{Q7gxx;)+O*l4kx%np!1oSJ722Hr&E!XYpMQt}u%Ryw%4*rYx<> zM@AJcLKsTFwr2d80;Rc`u-DgP+1Kb2NMn{6`&OU8?UMkjLx0_NhS1(912;G+j{C$E z?2+aD+;Du`JEF%< zIF|sBuh*#=*-(lX(hXppsSU3F)2=j1OnQhW)9hmYCkLaYhQ%a|PdbE|3wyyb|gNcUYW|m`?Hh<_{pjr+pMHIe!m{?*74hM)umO?g(7y5N!u**Bd zOfxhdlf)P@Fy`BEP0tf1$^#v#D2%~=f$rCUx;P@ki!Z#s zZ1{uF^%Y@$LJNh&Uk7)c8=f3F)EbF?6L>ut33r7_u*I7OiT`bnP_!8D+Z@?BxBwtF zRqk&DW?ZU3d>o5^lO|_gV~lnLE{6po=bPHU{XugHIZV z8*7GAO^5oGbf~KN8R3kjANa9E=+eW#T`n+6R)!jKwEw28CnxcOb76Yh^2A=I-)!MVvJ#3M5{v|r9~{h{1o8;ISl6U+ zCvTBCl)9>hreEGx3%hD&&Djh~9{oH6l1Co?uPiIr;vUbUd>C|C6PZLXwCW)lV!`rG z>=1!KDEzH6$i6Ogrhy}?fn}3`f=G!D2^zUzqE%)w(}b9G2reGvO#C`m(UG4;U%!f< zvr>z`GATC-4$++LMxv?3s^hhW0MS8ehj(`~^Zl0S$^@4)VNssHS%E)I=X10`(nH*U zK-j>dE2dKdPyI90M$%^kt&fK@PEh53qv3snV+UhWWfR|cor`Z$Xd}%n!3+7!%VZvk zeGbOtl-k&&J@QjLdc=qIGRy}69f1ayN(6lbPRi}P&8-ZDi7}nLSDI>{QGi@tBqb8U zxX7Qu*fKo8`6dC3x9FA)J-Om1V%qY1mgqk->EO+_nqVRdg({PH@W4Uu4go{j60seF3{z zf2K75y64|SMb)*Oz>HO{O*zL+h9%(qp@N@pwpZb#%l@XKk9w)FLQdS~D^H-w%}0MFbxO!x#uhu#=>ulSi<^%gaw7zI@_=I;et2PSi)$kjJfsUD}&fnt&AQ z{sz$>4Z=#l2TK~9mSGv4HgoI2i$!L8=0^m7*hmUu>4l?IvbjAQdC95j#Ku3o-M+ zV$o}zHdv6VevC^o4n%uyYuMy}PYVHUMkc-6BCCfLb(BbBM$BuJ1YwsIVX4h-1@>)e z5df42XBzvqOK|=dW%t}22i)&_KX%&Kwr$&HV>@YV+qP{twrw_UY_u^u_p}$zwfEWU zKIc4v`73M9ntXqs*Lx%HM@eA)Yb5=Knm1p>jQVWvW`!MX75!GtOxs{zn@>$!-%Z=? z_U(862T{L4?40)@|MyD#t$yg%>)%@yM}C(8%$@OVzl(InogW{r*uQ7xzmNSwaYekj ziJSQ;@O$6jcOm@myZnH&+8;!yx{yhLlMiMP&`=m;Y89wXN7ja2Au2Ff9I_xK;^8oK zdi~)H?gJsFPV47_i^)PFXCG zBUA#S5M)9s28)HVG3H)Vz_?o$^2!r8g0@Ml`E}Luuw%>DuPe* z@MoQNvPx!(DkCrGw}wR0+;*(cfD_8cm!)<#5fqt>LO-c-zBDdRt?1$d6wuuE5u$I<4s7E3N z1I+X0JstPPBH_=jka^E@)_J`N5&aHs&fTbKFgN%(ZcoQkH+o~c>g`@T?~KI|-^ff! z5FdCADhh{@zRA#lZqg`G18}^l`(xXuU_{;p7NZ7pSzd2yXQ0S_Hi8F}%+o`jfX4`+ z%H|+4#eVZ1uh>I?t1B4SC8Hh%ffbRGz;?d0uf=ms2^wp`@m8iD=Qxn+2HxwWCeSl; ztg12cb;c!X99+Q1iJC5vW$8nkKZ`Rfzr!>2%%a%U-p1(G$hPL0I9H~Uutbc92AL+y z@?OZnl;y9*pia!^+@CkkBH$we7GkBUPZhcHlatB$^}3rBr7ucS6iWy3nwC&(c$(Af)h1q>rl#m~t1nhGk8oC&M>T4hYQ!0rSD5s>SnOyGfdK15wHkkmx|XM{ zdIw>q*@UXq1Rh=SuD%-js7)o?xrSY?7yB3Pyj(u#%goyi((5GS>WF7aN zk!j!5Er+=olnN{U4|w=MP!N!r+*Wch7@{E6jBPtDl?)>yJU?WK5E^q;iBg8IiTfd# z3`Ki(Dzx?GgU`BSE{s&-*+ZPwqBj znTeYxM^vuswb55j9;FSiO337JQlh|?XOlPRS=}J1PW;-bRbl0-%}{0au`Y)ej)4_j z1g(Mv5_(~dqtJcR>TP^yIDD@-3PKrKOLGQQbkl>#7Bl}1?+NZUgY3lmIv!n-?*<2) zlkXeH4c)D3zZg-E%aY>%Ap2UK%n_m4pY*u@@P`)g*b7(enM9F|Cw{>ai>UWJ$qyIs zIx8>#r|f&xcCzDzoMMo7A1VPL@Daoj7W94iZqeua^dnr*@8zVt&+qMKOwj*h?+N_< zrz<7I*>syA7{+`6w3s0ndPM(k>UftMA(S|m z2uhkm2rdF4G9Q-^>SVkjv8@q;*%uMCq*)7Oh&_ZKPa^oh)+}00AxuGo2yEwP5LCW> zWW|bMxZC+qCOJaX{0PAyb>t|)W&@<~h#@RpWM4VCB1~!zF=mW}7&A2kgAK}&=f*@o zUv5&22h3qyzlLZDu_D4POJQ~nM}iKf(3Krtz@bNi^}IZ9Hu znmO8C#S~u@Yf9-m1=o7IEbXjQX5I7=SD)5|LQ-OacTPEbeWkeFj$^E}Tp7#U^Q^<8 zO2GkLxp1mywi?)7(#3Q!Q|-iXcv5oVJ>IeC_Y(;VsOHrA%W@J>xY>X-wvZSfVs3Pt zxl|Igj3v4X-c+t7Yi*TM$k;P_1De@b5|^})6k;ip33-nsv^YjK8n&xQwUlpY*&2LS zJcS!e<*m*|C!%Mv=`ykk91j(y_hy=RFH3@1OxdEP#}Eg>@--~Y@xD1^ir>#CI~LKi zlxzv~_GG4$k6UWpRxS*#c)oYvuGAv1(;2UKuC`X)g^RS90JPvU)F^&C21+M;p}n!%8uTt!ZRZ-jw2iYED1tyu zBn~fFaGsF*M9U!OeWCMdl%qXEoeGroZHQ}@IYdbQ+Gz=9lYUksp?ifv9W`Qm?-8SI zXZw^-T3S_E1UaVW-JH^hOGUNUz3eoGk(^!IKw4z6WEZjiO=@cW0bR9x0qvL(Uv?>% zr)dDL&Wv-#YS&!Dy|7!2By=is8|1S`%a4aL^*LCBntjwldie_JZEF4KZy5#LSLESC z7khR=Yo*pPpdH9u%x1QI0BA(vE2;@byam z$4V0;pLth>l}dee7U!Ywho9SSlA=p$(5QK5*hM>LxJqra9z0FCMbR3qkM~&3YV>g4 z?tDYpkBx4$4O_e(Yhy$A^kFYFG{Ms9BVF$k3GKdsjJI@m@z*C0#Ry~fc`o@MUpout z4v@ir87tPmwGXGVR%^p)5vEfW{J6B%*1-tfi*A9w8t=Y-*!bQD<<=0&e|deC<5%CUv_^`;fc@GAow2gug3$kKD?5I>{+uM=&h0AYtqJ52A-#z?C1nycLVw^^8c zd(by8o$WC z@`>7%SIrfCj2DbxIv-6*7juyRa(OsUt1E8Rz(?n>TTM4kZjd*AxZG(`1s|*JVl*mB zo(ljGZu2ZSDkXjk>@Z>3Jr6-l-nzyraXC+xw*idWI*&bPSddge*UI>YoF2{?m|s26 zsPd^h%i3B0=w02>c_?4@e=8&+@_Snt`{4((pSUTria&+|!=Pqq6iPI#w%}+ljb&sS z%B?XGL6(NK2!rGVgJpf#GHe_jCB_uw%{GYzszN_nlA=}x>P{HIw`gAAE5tB@?jU;I zUYscMyPYhk=a=Lm48F4TkuX)OSaj%=mK404CWjD#BJ zC`MOEUc@dBWRV7^6K&W8Jv~^j)XV)kul}bZeEmlerv8^AEFNk7FGV;Hs0hdXry`sT zRD`pEiZK0)jm;+%s~h!a6rIDKj-%=lUl3ZLB0LQ1qyA4t7?cSN^xulGhziw(Cfz?3;dJG@|4@YK&3S=}a3}B)ELZ1$RfLOINXG@h)(-6S zK4X!8hmYdVu`v^s{`N-^1|uNJ&}AMVOMCJ4spl z>pvA?fj^3{v`TpRzZK!me=5S0|4R|p|Ema}#3|!zsoRs>02Sf>flGDO5n7-k{Q6fB zu770yqX;jO|51cVfQoRhnH26{MY#TtBK*GpFGV;WbKfb-}Zkh!k<6? zQG^ZusR-jLeu-;F7ry$JB3uFHiA1j`ysV<~EL`oNL}yO?zbnEwZ2wk-Km9`yHeLFw z2*dnQge!>tD#ECXLH|cZILx$w0QQd}ykc`~2~>m^{wl)0|AQh-<_R`ZED#m?R}l^^ z0V=|a|5Svf|IdnWB2W?D{i6s^G@Fvs4fFj&5sniFD#B_&ML6gmiZD>={ofVg>HkoK zDUzx&uB9w!mZ0p@aDuk48G-p&!iHtfaM2TfqPlHbV zG1KnF{)r%l9HxZM`m-nTUR;9m^1&tkTmZvf-MMi&>-BzWKltPIrwQjJn(t^`4>^b- zrSL-DUo$5)>*xWx92G>-U?7$XtXYyGhjZu&fVMiDGerDJp6XepY)`xGGizzC`d94W zkjWA_&UFRhXe2@GcUD*f82%;*Y!Gr9WDv1iBTT3J5VPGn^`|OLT({1)^rITX@6ul& zKaWt$%OwSCN1qcx%69p)7v&dKjKqb(ET(3Ne0JLorjD^(w0mq!{D4-6+DRp^bTPz2 zJh$pCe59HyOZSwt(Y6Gq3e6PLZ?40a;uq=KSUhf$d$yF}4KrQrqLA(kL}dMqwix$Y z{gBw`$#hzUy?qhKN! zv<>pwbzNCv`|N(3Mg@0!nd7XSKYR%H2i*sIqkx0>UF2PUkq~c;mYi`XD_DSrZ|&NB zhk3;2B@WNerTZ|w8#f01d$ZmAIDS1uv-Et-3~uRLgCm3R9+ zvOe+h>$B~)+QY|+7l#|KoxcGU*b-Vt`Qp0hyvioDwEZ0-+%d0L*gNy#Z754K zUtPhsc8-rZi;zB=mNc|MGqk~OmV`@g#dNn^6EK;qJ1u~0>rEut}_iW*>o2S*#5C{ehyp*huy z=`)1O@_FbBJnNICvp

6y32~G>MCF*`1}5lC2q#TC%E0p^1VA2_5L2skul|+UQfc zN^&w1g&FNUu^X5OZnztgLUBHxaK1?TzgZajgNNI-^E^-(X6+fL?74Leg~N@wA*z~= zlJY}9u&my(cxAYMZUUD{bK?d`sV`bMDwsP~f}7v6dZuNlW>I-c2n(8~>6qN1fkN1v z1D{<;+B39h)_?bMr0`~JQR-_`k1|(nqKY=w5WzGC5ZSkPUGaV`Egj0Pi{W6Cfgc$@V2T~Knn<78UA z`>B`vnv)nz2okpw3U>$^wUh9gYzmt5qNx+@2|8+K;uq(56^$f{7q0zu!|4cLI&Qz| zQ`c!R9T`nL`pP6-vX~tJnOohsZFIN=GGv5*g}calxKJh^v6%mebEb83T*Yjwyc>;ZM|m6=BaDD~jC3m%JOT+*Pgo>3=K26QN;N$)Q?o zCKaAKFqs^vIfH){VXl`5-T?DEpdxIYk8YiROP!10YGNZAb^8k)zbZmlIz@DXDF};y z^FWE5Ci>e;EX``s^r*2}gUzo>^IsD-{7S{ou=(wtWJRZDooB^GQjSJish7d2KiSO- zgWV-NBW=cQ(B}P44_UbYPfW_^5Rl2VJqLxA}Rrd8cqXhG?rt zS@~K4ELu#!OFC_%g|=6@M^w&4By+8~IK+@O5E8D(C3O~OXzMXWYx6ad3Ugk6}peh^L@ zuy$z=>Ie6QkrXza+Rm)Z&4}jYa~%=N2FkZ)9UviW=$Ts_fLUhUWn}in6H<4xr8EK) zy}HT65mOLeMLtwH6Fe;inmH;we569uAu7|e6-E44v(l7}iuWHvxT~$L^Lxc#Lbyc} z3BFOOJzSQ+y|Mk%UXvMovo(9Ohcs))MpUJTKy^iwDYpc@Q5&Uf-MAL~7G?$MQbsiT zA3r!Ex;@OMT~kTH9XRS_>S~g0y%OWT{D&WW=L0v9o(R+34i~x1$(3jG4JtdQ@*jTi zP)P|~mef#Z%|&NDJgU1e6rMy^({4LfMxX&;HM4Zm0_X?7YKA*=`8#^}pH*|7Uifo3 zc0*==n>_pD2U7$6V91^c^`3Cq_Mgb0fBfM7o~?@>WQ^d6Dg%w@Kta+VM7&U>Y1U8E z280pVx4aF9)_?ur;t)#{8~IaxOjy+AF6x2)mY)~v&p&xSRvW?edHx|^Mv0fPff$X^|ym~=;&Y6zMF8f9}j z1FIFn&MW@l!5!cNcy-j?z`wo-wlXqWlRtPcUKB0?jdI9TO9}Fb$|Xup;21j!C{|Y? zo2;@t^?2aBF%iuev+^hvV9I7XG6!&19RDybn$@ZcHL)aiI|=X0&!DN&a!;%SRZ3l^e$>eIrw2Y zEUT=i}`7T_Xfkukr15BE3^s)QzpjXneD7@T3Mkrj(7{wcrUT|yezve zqqt&ew9}f|taLQL5)|I8_3dY8&J^Y9i3NUrJ>UEG;(BKwb0o2iniuJ!co z+NsT>`|Ul%oddnKaQU@o+qDP2PO!l(ug*Vyu!auPTvzwpl*E46Uq4ugm;q@QYjJy@ zw&#F%pG1GZj+_aheT!&j9J(ue^@xR`w=Z%fi1jWA|2H099Pu>qj==T-h0MX`UCy}Y zvM$fz?ODzQcJ8>ow<6FF=3c#I!3-=o>aWH03OwSITUEwCCc|@5 z_6sAM-__$e?1%edO^^%SRXI;RZ1E+`M!ki=B+TOz?eEHAABIsGKFpb_qgmopo!Jp9 zz?a?N^%IoG6KOglm);ZW3|?dyG8=@0v^W#nn$avE9_%` z7r~=3E+(5&EHLJXcW&mb1Izjc4_-zmPmr6?S-N<=yGX{erOc4MUe z+$+8-LjBJGoY`Z#pKy#q?-=pG^DHF(Ed%TAw#IEPP1O!Y6%=9>S0E;XQX@Lx0?bV~ z0M~9GV|Ib&<~C}6f%fw)CE<4x&U<>!#oaGw&_yMd8o7KOX+ejVP|P9+V)R8M zn9Bp)ro~~nhcTLECe#P=S{#$#PF6k3G*5EUABjrM=rX?O)F;4|GzuIs+#fcW2u?)# z5uN(jGWT&D?MeUFBbgAo#pk5^n6a9d4~loVBu20<^EtB z<^Nrc7qL;lwHW{L-TniyJ=7XI{WA73?Xhhg6+i^L?aK@3!9>lep9K+?C5m8yL`+jI zIo%x$g~b*St3WaqjYO5+9f*J)kwC-#l|bdeOga{aEnI{YnOGu;LN$3wb?UG`m4Qwe z)$K7+tdPU?>vVb?l@vB#h#BtVi_6Jap-eE#hZN8Zt|BVa;D=$|m&?+zuukPhu8|K@ zh!-K}xj$LVvyQDBc|j@@t3^7&sPSe#8Iw(aJYRutyZKQf=lLm2=b6#C&WjEEWmX95V zx)xcXni~_tz%1p|Syk)7J3B160BlTeGEZdJ1TJKxe5O^M54$p<8 z(2n34lpy!w#x^5MqgYQs3?mk&Bn@eCk&)G8;)%j?rbNLj)H8HJ)F5oAv3_pYncq^J zVG_h?5@2$lSE=E->Qt@c6W_e!X4WBTYG>WFWvyg~6-NN@(+DFZPHLNb-Y+2Y@_jpuQTq^QCH>c@I;l%zTH-6TSLc%T@`Oh5g7{G$2E!GWA)^jp`z;pF76pO%Cx;lfU@K<2`t|W&( zu;uC@nt1qS>Aj3ZoC zzwHhzFrVaK!LwSVx)CrnL!Rx&STzdSbP7XQ3A_T1^FqtoPFRm-a7xqldN~amO~N9I z(c;6>N}AZUHFonGN8Ebic2}vt;^wb#+nqcDtE+mcX1oqU2i{#@a}OEbEjA=p|AM%z zd7LzB`?#Gp_}p{1qS`m?(l5>E_dJSE*cv}U4lOjbqYd!A>zZ=j_7Vz?uAjLUJ@;$4 zDW4N?!G#>g8ZVC&OZb2cCF}FLYx}<8UDVO0=u`CTBWtZO+noS}hj z@3@c@NP)+ynA!voq+HTUdQk5J;J6V4ymklx#>3YFXalf8^I@FBMxR{UMG1hnSwRS6q|kpT!eVsm$pNln6dVhYiXp~mrCcL;3^tK$ zK0+9Ty8*f`3(*D;CRig}5-e#8F&1JbI4i(O<{w2EuNb_!T^#4rk>-~i6NZRJNrA_O zcz*~}B1mp25sbxza52+=D8fz&9T}wff=-g$*2?j5!=@DM9nuPJi^#Q)FvuaDm(E>aD zRRJ|;$)%L-*O|2MwQ54u&l65??KyF<=KP;ACwS={^0Fu?SWm;`LYfn^;woqf81!Tk z$l6l2Nd+mhHNXd+XA0g~OSz{A<($&5O5Xd?u)m&Pq|Vz=Dcy#Diw}QWb!+g(hWyMUZYnXAXv+;yskPFaWv9h zo!B5oYkbF8&9|7L)#Z&^Pq1EX@kOstdx_YXxLs*%LO<0Hj$Uat=()AKFxnzPH`>;0cvT}dgR6dIywYE)=MacaX9S_x-j4=#5rlrZ3#0iwfZ^uA z%pJ4m8}?=RxaTW-54;MP|7}ldC^N-F#{xQOODbucV;s7bk%ZhLMXx<4!GyI zq=ZudI^aCO;2YP3V%RMWmBwso z0-d{p*c>K_30-qzOYWK79+upuO=)g_tvTP6lXzC0wV~tXk`_cd%OTsP{Oh~YAjorh z%$d_vphl-YVxw93W+C#LF=^FvZoPtYei4`2y-<2y8TqoJHrLjt%6^fpjHssp?>=jW z@w0sWeCwVgwJ#3C(YlgXNB@bvZSCl?F1cD?=Ph%|RsUAEjZWpjEp3hO>s3)~m$|u( zSMMa0UDS}Cp1$Psdf@a!^9tVAT@u{2CW5PmgR8G5%gP8Ap~^Z(876R7UzkRcB1=d4#0cjPR)Hzef`)!O!w3ep}D}@+okLR zE1M(;g+6`9rHZsU-Q^Io*SbQ9%WeC@0NQ(PMBuS5xH(LV5(E8TimXbm+zODJ6-@zI;^{hy_4V1p;uFpn!(TWo^jvb4j{3FPKbY-fbnLS7K!H@ zLXdLeDEo{pbCxtb3kQHiU>^|+_9yfB-6q(7fINNTpo*2c_CF!qwX%QP6pgCR1@Q7^c1?ndGQe)wJFaUT4i82sl z?Bc)aEAs}d_ud#C@Hd8uN8F0me@-*_lrjn66UoVYpW_vn5anwU#>Lo+U_lCuJ?(xy z3 zM8bT*jB1XDe&fF)x3qsFx7e0j3ibt}nsCf@_U2O=sWPrnpfonC^air7J=)fn8@0X@ zqYk*>HXFTm)t~ab+kOm+Q$zDO6x2B@0wcF>5KWN(d*s#}{+1aW@eAR`<}2vGBe#kF zEpq!b5b*L#)4>0o94qo4kz44JKapF4|A^eKQU8tHQv9#TZ6`|rBrtM&0P=qkxutMX zGfRaoU0dYBWO3i)VltARPt}U@M9wrR@;J(}5il>4u*~Zqj>#-6Cq={7r5%gHQ)y&t-btY%8k0Q7CF=5ehGb-IeO_56 zkhUQFwP^BK$1M-=NK(Lp2!cj?u^naN+H}5Fz!(iyP2|_FPj0K)2gPgnZInT_=G%MA z@Ud)NH;!tBXm?1ha;d&_ZA*q%*J3qQoy@$+V%^JC*|)`EyDrX=`yJW4bEzwNIk=0B zVDaPVmEJL&%KESG44yywWg#!^9U)Ch4~CE==^W*>GYUdGz|?C-hVk4le+`2gtLFrT zhh1jdz>!oEO^#Q^&`pu}7c5V{5ofQ1vCs#w&U)`|4a)L?_c+T6fXg>WZ=pOe)HAZ! z>BrggZ@Y9W(9&NlE03i#FIl~C-Nu8yM&PbN$h@!zo1s48Y$)e-6RvU4BTayv>|IWR z)lFYb`kZ_Ke4b=HE@qx~obGH@Yf>Mq>-VKt8S)P_Nf}xWwVy0o*JZTxN>VZjJ-JWD zy?S5bNuqyuB&~=$t)J5#_3+5nH~D3re;X5c>$(%q;T`T0-0JE{$;Rwn9fF=LR+G{` z(wX2Z>b7@a^*=(pm1P0k_|2($z2DbF>gHb6)gQuN?uOq?KG&xEuP;h2cs&na+rt3f zQHCl!r@~lnI40-I(aC>*S~B?h9F75~g$n4lg1yq<6nGe^3;aZ9Kz5EPI6hJlR9jpC zMJhqiNEAsMx-UN%1^fnku~&kEGtw^jMpf3J6r%aE`(;)oA z@@rZzTGZrV`I(Djkk%&B*#xihk!>FNOh^D{7DkVXZf)(Cl-<%naMXi{;P2D8KsCb` zmJCseM~5K7=n^tY>4{sUD#-vmSv#l+X^c-+v=PgP@n58541H0OUqB0|f36N`bfP5b zR%_GQ8@CJ_#ri5&mo7VqjOos@q{j^k!OG018Y$c)SuaF=iHj^T!f1k+CY#buJEN-P zx&t3|LE9nX8l5>+@{Kt(zxs{QL5iVlb7Go>v{Z@h4Aw|agG#~N2s=Y|=E%`GFjMH` z0+2V^aOUg}l;?ZXnmc=_iP?1_7cn^L+V2=HWUtx1Nq}02oE%fA#-_jxt5o&}I~78F zt+3~rT!>x0D~3U-$DSfo%V;rvJ=(Xgg0r_K*=yf*S@u3-xm6+E5E#_lFrbs2 z1G+2E7W{Oh$+B?e^+I zoyCvsi$Fv?eZn-!@-L%jZoj0nVKvhvGf+ zK&ufYmhRyll0iFEeO{)O{emsbLczA|uS2g=;#+^8#nH0#2??INgU{M3JHa=HqqX|O zBJ-U&)e|AI)K?zG?X$P}hp;ID_?DFTtioh=4~^r1ruFfwcULaNYAb3*g$jn(1VF-^ z2Gei)>aYOov&GZU=i;AA1WP+Pq4+(#**AN)xVfz%H{PzWPKn_;i|qzPhQhn`h+#SEF3PtI7^+-Up?ev(J&o*0R9>$kG^SP%Kpq{g&$ zk9xV+w05$#QaO?L@@Zjq?~|_Xxj_qLehbqIV~jN>d#h3DlpUa{sMJ?g@bcS?q-+OM z7|FPCYk*rW3-%j)b5E_kJyoyH&QA`mzIA#BaYvUTGrJ1$fEu%aeGGPZaHecZ9fVU) z=a7IybJQN!zp2|mhPQj}M;D8EOg?dEC8ni1`p~y#>E`^Y9Xtm`aDiSAm%~b zs-faWY@}Rldm{=`Z7wYsVd~{Bk1WQx7=Fg294|}0aOTF&$^L;u{!b_V)D&FKFyX** z5M(Phvj(=~7_a}Dl07uDR2tukvk+-AKg&|M4<$1_VBXYrELcQ@ zFmsW%3h&%wnc8r5?=;)25nofTFvIZ} z99Louj5a+>!z}T(=hhe=^RamFPG+%beoj$)@bI;YNsq7?8&{&sjGcmsWx!6JJtaA9 z`;t7ucwj*lifz>Etf`V_yZ0QmRbjio7JJ7Ta5^4$P8C?RE^+OV<)9Xb-yQ%Vs)LM` zWm^(u{gMzEnKnU{(4LviG@#dnq4%1~!V+QoMq#)s8ac%6i#!1nqXZnYBg7yuFd@uyJCVKQVrwOd0NN9!r3}i(4OAjRT!s^nhx3rN%=qq6HY#)G zx${?Fa_+5iA0qQ#xhX$O7$HCA171QSGm|4C+055G^|>;+MRP`|cs~PcL)4Mi#7)bb^Jf6bWX)t0dpy0|By4*w)mIGok@wNig0 zXSxIB$Ef7afnDzxsgt$1lE`=lW{3r(>IIO>V>hW=Dsolu>ima}**uhLI!0`MSJ z!>=|o+z7`FilFWeEiE)D%3+(1M4fwJREx1f*9>fZx+EHAs)>JE|R@3Mx&&Ea}Z%}{(s5rc$0;D?b z2)Bu+C+d=icSH=oT6y+_1+5X9hIdO}TFW&KwZoBj$fkEnl+hKcplLSLyU-^qp-%}q z1VC3jt-965TTcNPAt+CG@I4~f^ za;DA|Cgskm;tsYrz*~DFZAbTJ7n4zk&rhR4+)tQ48}Tfa%GRrj#W_J&{XHzhA0@+I z!~1-l`#>#$SLV*X zf<#n<@Z~~@-dPFW4M;MuL2DW=HtJs3Ic%3gY?5u1und4p_XGHjyrj=2xP*K^Kcl@5 z@%4ib&^8}pH$2KDiUT*ed_z0fjMO=Gh?_a27>c<|9BSQRD38|qqXqWNt%uoA+&Q0t z+1o&*VRO7;C_|9F-A3K5(U$7=tKo_xvI3p=;nUY|liUaq9wxH;ERj-7ndn6w%th!c z?It=n#(bj;fCcQ2`EjfFaj4x!qN*lL$kbH12^Ni_U_4Z}%Wr*Q`K3fcQZ#Kvx=~5& zC1o|Wnwi)jhU0l)AjWuvfxF`$OrJnNCX(dZRI5tl;kl;e6Xoj1d#kUN+;}eTbl9^jj{@O+Z#u-+C_sU)@-REL3fPoypbdo;MVe zIj{lb4NSF{V5MU@duk%5m{Ej4Q2JqWgg|nLKp9YAq+*wabEa^&mJ8dKpiY<=YoT>% zsuoL}i0`0Ta}~E zRC@-Ct&>rvzAJJzs%SQn!lN41BB6pVA0fjec7J{=SmoFUtJ2^cxQ*VrDWi2VtV2F+R8GTWnGDl^c_FlYAv^=9SIr zS*Ibam0q++za5kLbBl9!q(;J)RPL5m2lVu>EohK+qpqpW_sHd3Y#sR0FO8er31g*z zpBfQU{NeCEG3-0(ER+u>kcR;Xmv)d0D#V^hKRgq_aKL5{_|l)~XYI~?kL5+T@N<`6 zI%i4znl9E;&@(?BjM5hF98PVWLj1VJ|8dX14uwAk<2(N}?J^g%i`BpFkJHq_uA>*t zv=!a6^(JwYwng(vQdEhU8fgz(q`H2hisqw-&F`T7D4V2r z-|n$G0#@YG3GGCa=2;W^f#b%gGdqH6$Jq$}unAf3ls1L&Al-|RY8`~)X3R3)tS&)& zRUv)W$q&}6GPy}KjOh(8X(^t9jNcW7`*;Yn|M zy=SNG+RbLmvV^8`re|Vqa$L%O`&lx9Uhn>%S;+aJS!Vsf@RRo=I@)cT-t^`Rsh}3? zjXm;Qgv^Gd_T0}H@!J}A7I2%J>3KN*+d7IFke?N}n`h{8-Ox0*g#NeW0Kz-2uwS)l zinLPkD0T~IJ$KAYce{^wC0SK_VO8k9Ra}Xf)D4Ze*PgvZ)Yi&C%x~!0Ji|Yoid>L?x^na!+L|Wb@*K-0{WyPjvbEJ)}=A27n$F z52{Z5Oscg`>b*W_^!gfyi#uE@ELtq-<+?+a48cZR0$iWc`;PuS=`^Tw;Q znX{d;H%3%ox67)-!AQC>8P7j`Lxhxslmghl%>_#&BxIquq_o})1hBa0UcHYBZb0Mx zp1fgN>M82W{Ut%Nb>63@fU;%w8IWu78;d{yvgH1UJ=clhy zq4(yn9trF|Vov#z>w#UEK#0bmAS(u3`AwdF?L>R0Q1 zpEnFWjUmX-?W#RKl^ji1n`P~C%!NPu>H3W$Y^SmQU{(P6>bU~xW-)G)h2gd9e6CL+ z-kJZsOW=g_P*xw{_xnS3UofKQ{m}b!f8O+gY=7{0($^9dnaVikI0D(PL=j*i_QL%P zhYUj@95I#y5khFpg~+)3Nc@PBys;uj68oneQ0dW3qp)@%*Q40AvJ0Z2N(c+X==2D; zgM@^5P=ovgF_d{KVc6yq(DB`^U=xKHs#@&DRS31Vl^YnFADy+2t7e5G4%+5TDXU}r zS#0HchM=zB^@Ivts;JY=ldQ5OeC**6#E7~5N&=qUmLi12jMJ&Ub6Wq5vY`w1HA z7y6+eSFnb`Cpc@JL5K|Plm-WO?pR5i^dovknZZ#~4>&!mN6}d7O9ee{*0L(szXv_* z6wGGtB{>g5SXZXPIK1QwTroDx^H^^?O0x_7t^mP_ilZBcf`qzSgUIA6ry_3x5ZTi) zGjCj`#0zDzcEN|FZ^TVTHHmB|TWp9o_|DT^9rZ^TI#O|;84~RV<(GMElH|>EY|7O- zRjz$(qPmIF^a;9mgSgeCoZC1UQER?YKGg%K!xk7n7RY<3?&h}lw;l$FgHSG#Tl|uc zw~Hf;B{ZoR3n5~HEP5z{g9v*=_6L$C*pFQaraaTr#z0;^N7TbgcAeFA@nAY1>Py_T zq&tx9hW6=u9+U%wUK{i5e_%e__3`UVc>Lgxs$8xn@ZA^fOL+KANu8rhrU7*y32GHA z^cz;m)67eGF#?_59>1_n-U^xUS9A-?gMEyH~ zo`y9O1bBV^SLF7;ou{jit^J%dagVtE9l7lrPvWv>2JuG-09j-HujlFih}^Oyf`OP4 zwX`R=y)Y+VK1))GbIYit{jbPv>tbqsh#8$3_mtW<(&Q{ODN1HoDW%25^gal4rciD< zW2mLHfMsKmu)PVv$8Q;PA?9qQ-11fgckvSdHfUDxT{&yFC1B*%g0r?#TF@#vdr!;^ zs|lnR1c&jxZV7ht9y^9a+(CB`kMY%^Jj@#4s)q@fiz-JkGrTgwFb zEoW23mdO}ZE~(tAr3&~~(tJb)nyor#)6!dt(Bn*&YN!>mn^~yx^C$-&J69HWpQ~q{ zFITWM7ic|HXm)h2WLZB{o5fmck65o3d}^rxE430i(q4>jRjYFgJykoS(JWJOt@l7D zmpP$X3*JC455ccdFOFL4;lOAtHoXLxH1aHtZ?IJq##jk?t}n!ktW>7)S6DpotaOL1 z)aV}B=n`8m%rZO@R?1r&2xf1TYooQ6sL_h*cxz3Yt3>0npL1(gt8MI{mn+Rw+e&VJ zKYUbgNFJee^yX3Tx=t%tM89%QywL5H!E7UPtubTdRh!vJE>owk18(?bO3&Ro8ub`` zM0vIQIW(I&)NNgVz-w16KDGXAu{Z9CR=%Be>8wAp_Xe$28m4J4)uykp1CQ2*RZQ#A zZDHWWM^J}u;~Z?Q{i)UCWwc6xQL#5&6DS?I^j)BBgkHc_R7-dM5Kd#10n`T<6)aJPkXiD-Vj5tf$ z$onMu9c!8W_GQLOw>g;e`jms2bIuW+8E5)ah4ZL$USXv&FTCcQXWVVR^n?X^Im^5t z`LxZ%;e1_bk7*DTLNkH(tfdozYFFI>6+2*CXWvZ;1O;rR7 z^_n%kdoRU{^YTHQTD{l@+qup)@p$&uCUJ&JfX}hW$#Z>h?RBF~?(!>7>-r?eR~vX- zyHVq;b>J^WqiESP)$d7DERYW+{Lw}j7oDS4+xGs_*~@Rg-Md^r7@SXNZN9sCr&51v zD{k`EbxnWi>`-ubKFZz!42*j3o~F6`pM4m6!#`~La@=>m@Y>6qV78t^GL2B`JHQkA zlvK>L$M|ml^cL)1OK`1s7Uoli)@eVw_u~%W?RNTA=RQRE<5xI)jHb~A_Kzfivp5qx z6M}TlaU+4wM1O=sQk&-%ggNG=LWZAYnEdeUU)d)3XUulN^e%{JcqXxN9_#%#E)2rU zN|nz{n)6v!s(PI_j|eRM1>_gix)Bo1f z_X_bjBp39Y)YJ!|;43_0@AI5>*T3!bM*2{odi7X|yC-knX7XqgLBE|vj!Q^ZKWy>B zxUPFF=rg!h_vrh6_y5uMmQitTYqoGf0t5*O?hxGFAtXp}x56C?cXxMpcPOB6cL?t8 z?k-6ncmlWf?tA*|)ApUdU-#e-{}^NO%y+FRYpy;CQzf}W4$X(9dc4n5@rPRZ2xS7lYP%LaKW`WboR)V{&)|O}=}b1z@MeBO^R+^8 z@4ucze%=rf6kGm!O)hlpC^-19zBUYi0S532@C}d+0K9ntym~_@QIppb_y&Vcd$=aQ zFZ4aRRF*{Tt`Gp5-C}*Xws0u+0|M+ZW?j)pB8_svYlZ5Z(Nq?r(WI5xgYirr$5XH2 z*~7_P!NA`06XnvGLJ4|w#*Butxe_wVrXZ=t(-}FXbj^*?n}gXhoxTXp2i3FXdNXRn ziHxR7tsIS>u59VlZ8ZSy*=ccPGxKJr-`3;rJLa05dcYfcCa)IOrT$1f{v4TP4dc>e4@%|OeRaM>0+(L@oaOV9hyV@8i-6H*U|E0 zZ#a=&Z?dEH`e?dPI#;frHiaKHYua8_SjN z?)v?7e|@$!)!qH_0)VI4_Ir(Ow(b9hs&qR5h3j}b@Vyw#P7o&0Y$q5ORJs!at;F65 z{SZR43%z!2wi`|ZF5Qh_Xgc17p3i9ZqF6GF3Zwgy9QLA%Sdg3W- z^7j)c3B!93#K>AH66Nsm5aHv$z#haafWi;r)j+KWi6n0BCP}yyyp#m84y~c|Uj}KZ zEH~? z_fp`*Ou7|XXxPu)tUx!#f-b2vr_8*hz~kjnDA(ueM5@w#^AXy#u~}xBQ|&-ko?KpM z0V$8l(F9Sz%i^0CCBufBgY#@OFDm?i{B&iWED^=bLjh-%&GCMgkQQAK@@bPQ>Pl~1 z_u<23X6GQUZHMco7IXaLb6HvAdV-}*%CRo3U5gs}&-0>$4EAvrA-3JZ;?JYJphjcR zqiymsK3x@amsfe|kXiu4RjR1XIAxPdm)23o!!DGQGmgnzXEC*pnNG56RX7Z8ggn>} zAH*;?jeLpZe_!-YM02#SPo1u|0c&dHbb;Y1%6U=IBiw&vFXn`ES=X`Cd9fW_dAn*= z?#;ENk1x~IV>m`s*9^;PZA2^2{gS;mcPPV9+wb*ClBe70YJ+{!iA)aqZzR(!?$HE} z9PHx?dK<+Eoetm4d0(qb^(S3r7j70OK0mNP8mf?3YlfJf&Ks6&+As3IZ8R78zI)Yr z5bPl7zMqOr0+`ROer`U>!_bxb_~Yk<#1${<2=`C#Z$EfDeVe|T?ZRZm@6xm!WblOdg59-t0oWZMevYHPqf@fSRZKF( zYIYkq9Vt`GfW=#0FRCIB|6yaZy8dhasP_)9D%zT1J$9R>cIn}JjN5!J!O?IRL2`VM zk(W}uptG0~>kltfY2!XCjsXIb_mPPf6y&_aHR6vJ@>}@Jt^J%uGQ^SkS?gKb$ID{o z@w36;B63z-^z=Ea*U7d{Ine>|b@C~Zi4F4 zN9gH;!t-zIQ{$lZAl#uZg%^zsZq4f^KiYs}e!8gQYvW)P4E)+)pt9XTROuJ$)rk;8 zc2@wS86yG`RdmD|w6&D*@k_*%K2=>R)xpLqEK};8g{$K2S(S8s{An8AC__iWjeaIh z9%V7h5&_P2`M@tT1^5e@*xq}WgojFYGb&&h?^ATy2&MT8Wyh!fnau*OMw(+3-F`ld z;oe7DWdZYw5sz75pj4xk%T35QIEV#dD#niCMZ+Q)zj zQbuziPSbMYs)R)flEL?shsiN#B?qd+bz+;>8p@M1A)oQ}^$ch=rB|3^OAqozPH;Fs z%cTTWcb*@xdGaE>Xx@bLlF`n&naX^*y!GezDDVG%P{|e_sc!Fy&hL9fIVm+^hf+); zCrztke!$YW4422rkMKEsqqJqLGV6X4Q`eC7NA+|DrpH35F6400eD1~~3uU1+Io(__ zw640qEohFr;5rGhlPc~!Z3FfUt<))bne2og3{txE42z(uuai<8;99Kx*_k!4g7? zQi*QMVIZU|b5)g=0aKC&IfgpxItukvJz+4Znuafw%^_^g&V}PvDW4JqEtYXir|2CR3wO>y3$CM{II{eWkZIc8}rX=DD!)x8A6`ndSk6O zIr3W;FDjcOp6#=`)gP4#_Y3ogW-6KS%%y>RO4QcRWm!i0^@yftgq0fsT8K?yX7rEH z^3Yx{&Q25g+__dyOt^bhhymwk<*9=X$I3nJNtut?Qr^gn)CoG#pl<7F&R?b!dwdz$ zgnG-flu{q3e(m^qQ71h&{A8}G{N`OZ*XsS{Ymb5VwuyA=ngG#+2%r5qiZboKFa3iq z^s%ZDC9L%E4EOzl(Mj&BZ@uQ9lyw$4tQB*WPrKjTM||s<$FR(Kq*!>^edMvZkxh>E zmoZ0D!%gcBO*_UjxY**nKU9l&njo)O&lQ*Y>59X^PvoT@S?y!L6x-6F{q6};$iH!f zy!vv5XQqANi+|Liy<9WX;lpW^Y;Jvn)<@l3!Ip1+G+OyG41K7NH<{ z3>CozS-NFf1vWa{dRoP03blHm?SS%txO(6L#kyyavqC8yxn~^MU}0s}Ls%8iihsXK~hnP>p0&8rBy_ z`!#5LbeeY+H-!Z*D_Vb`2qsMsZWt9$nB6dC(}8Zsf@jNu)`vIRlMALg2SI_uRM`m> zYiv|C=#h2HR7|)$_=^!^R7`^=R6umLD+ljO;V5>aC@E@czGYtS109i{5lwF*#Z@9} zX`-*c&|VHWXbrHehDEQJ>i#Yc^Esvn5T+DQqO$CzQoRbu;dDfyvW~d2ZlCo4@x)pd zhMXI@`H9Ayn1%Vz#>zQ_{&F(t4h50DF=5AHs1>F|GLNSJV)(n*f+Lkd;MSm`glmu{ zylK`orbhWVMEC6oQ|@g9s(Z9raVSlhma{u##R*)4ZCkg@$f+^Q)1P)iOT5HaKAyMg?9fVVLtGmp4aH4Ux9}7;jaJu8mt@Zxe>o#_XGAY&UJEt^9n}Xrb#h@- z3~G;bl~gw0Jdh=PU|>XRnmwCyJ+)wQ9;?=?v_xJCcXGagTg#3nmCkFQ9+1_%i-lR5 zwdZ%AEOvq7xsQcLuD(rHBuh3Eu7PV}8AcMBn_?l+ttnwCjr|`b+l%FFYFG+c|&yQ)v@!7b0B8!c=<4f&_a^@eRs63|iOl zRIl`aylKGOH;_D!D_1T$XH{`GLUAbv3KJT9>C5o<5gf)8s_t&)MTxN9u0yWQO0Fe8 zKlO5YG?sXR;HVX03)wQ>*@t=jOpE_9>kacIANE$SC`oEF{vAxsmoF0J2>D>MHn21% zxnnr^Loj&yJ;13AP>J>)@P9MCQ0_Agb$vfTfBu#G=tF;na-TO}^@W0N_+a9OYYas~ z5zoxmaTN;(f>7T%5c1BF4a!j{r@VHz-~N)!!m0FeIe}_4jTH;MBb*&Xox$XZ1V{Vc zPa#W`8D9V?k*c>qfb?pASmA?Qh%y1yuRHlO)t~_x2ck7+bE$}dHa6t)xN~(73^=A} z7)5ZY&SfLUIt@c`xzp;V3#-hbTnFI%8|jcvp-Mb>;Plxj6KJ;qp!i%jA$?1_6Ku?F z>wK1;zuoW#=f!b_t?_gzDiJ$aHj`CxsZo`ma+smnra(0P=Jq%6OgW$>ocdFkz1yW- zxU=Ct%9^o6hIaM~^3aXZ#2Mll8yxZxk%8dfSEd!ZGTeV%nGb${vcj;MJSZ!Kc@3Bj z&le4beJ2+*JhR;|mwg&sAzo)J8u^M@>iqb-{zxi|bb(5GoXKb!k3r771O}xzfH$yf ze`U^8I$z?flELH0&TtV=IyUDU&XPf2rA%}$&1B8i^m|^WQ`wK4)-WtVW};!omYmG}H%!38t)h6br<*k&A&ri# zfGl#O3rjqElMoEfK$rD<$K&B5d2(=B2D{N>l_8jBHw88|L$pS~Ny57Ar6uY@&1V5@s`az@k#Zf$jWhS3_HYqUdRRAm^!*y5 zX8FBC*8g#4DOKnp9DCA7>9@)UtC1gf7?#MFAzA7#Fn}HBooUVmUs|2z<a=GECDwd$j4S-=Wj2fQ#;O9Yd1`U^^6%9n;F%zFlyf>gu zV3A}?DrF-bOJX)U&CGNN!*lAr45s+7c5!`b@Y;H zfgnvR)ODI#%ke<<%n%*k6l*{|a0cv*-()S~FPQ2AF>_#AEOoI~!h%d!uLcv!!wwVR z2-X@RzQw?jPGnH&58UH3;c_oE9?er_O9^+O0f6Eny|F7;4@|~Yi5#gSR_hIFKgNTI zHEMB}3pA{!;MS%~EtBz#JVApRm)4op^w%mr-+!p~^=}BjjpBJw3Q6GCGRlegb>TV} z+c)RZo^oN6*t-ylEZ*e(d&YaA#M(S}+wABOZ9qroS3GvE&uk+%mIB~Ze9O{OltL-+ z6b&IC7_L*I=ORYyrtC+!3%@Lj&TC?*30`m_b)xWa%J3ePbW#@l%LgC~y6!yx!I-E0 zIp$EQ!>LADAOsf;{UdJe-k`?^k&y9a762d-PvFz*4|NAUzAWjCNfJthQb`P25nhPb zxx)UO(vYlDW$LLkA?1SewEE-WLV@%h84rh3sRFs&+x62#I`KR%WXLdnHv( z9Ybtz$AY*wH5bH<)r7^)ntqRAM=NFw4AGUuGy?o}>h1nq{k(to`5k_r-vgDN_^c%2 zcZB>=$t?)OYLq)Y-n{%a0^08gMG#PW{JLi?8jh!g$+8M#HIRy8aBTBJoHLe9VmAT5 zj#H)v@N_Dr^?1nEF1{^l3%w@d!wfeb!hO%A&mz!Rm?^aa8mETj@Esc zD!9<#tWb}!YaY!mzdc(BwB2zKl}4}7$u%BxQBt?6lIZjCh7W0TGuUel{>E3Cp-$gB zHULllHdLKT6`URE!!*wDQ@1RPIR~81ce+woPy*r*V7=<^AhmrN%Lba;=3Dr`q8VIm zG>TO5rXMH3;joV{^3G{Ma&nj%jUqCA>7v&;5jx#YWLoYGc+tU5eCG zl_u`Gy4mX-%2l{SyvI%10E_ZOlKBXsl5(Hbve>^43Up2Yu>kMC56Zu4 zlsm!z7=Q#+qbwK*NBvWy+!F)5r0EcvD}MMAOQQ_Y#t38-{#l8loaBe@-mnh`>ywajPFq<`UT3p)3cKEd_7+bj=*d#dxz3NhN^r$4Xh$F@AL9i}QjughzLuh5@b+_S3QQ_M_h6f(%XsB+$su+(3Vz`gWsQ&O{O zK1#@>w>c?TxNJNtAgFF@8Rcj0xRV+yS8ly%uk4D*Ongl-Fp9<=CDg_}a-&Ims-9Me#~G}Y0{ewi^o$ZhaAKM!lEK>b@D}A% z@v-=Dmm-1A2~|FxwQEfEVV@|{Td%GT&6?~6u&ctJ5?XSHYhATLhju{&`s2DiB;*G=!>qw)`VN!`)Yv``U5gIANbDc0``-0& z%tT;eATjqVneY_0^BAH07)^uwdj;cTl(4MTud zRD|y6XU~TVv)dK3l8ql}wo2Km>5^jj@Be;Kg@JyF_5M8;UVr`5Eh3=%<4Y_W1c2o* z#;zsr^T%V3Af!bH)cevX=NJ#p7>T9gOO9rlvq7=&(%ZWJU=Nm$;Iv0-Jc;`tAO1NJ z`!!1gEmR_nB~#5vDpM}mDY#AIOQw?yRm*NVFH?mqRRc~rQPzIu3sxCV=~js2Fsx-7 zHTNcavNCS8p?uqPdU9dj3io+|ZPKh@UF#s#%MkdeSZkQ7MoPRc>7IWu_LcxgYYp4N zAdZ-y`j-{&_wK|O?RS(i{Eep*6(=sR3Jgu(W;#uAe&3@z53Rvt_-^W;+*)oIQ;IQ^ z<2}r--=sZ(kaT!fcKfZhUZ}%#Dpi;3?CXLwpYGk_4n(+{=#%VJ3U{{Cv~ms@~c;eU=^3wV)98^MNP7n7lciH>aPejcQ)5)L=~k^6Y+g(iR-+?HNP4` z!_|VORgiC76^*+~^TB&lG>M>XcfiEjslY!ovj)=hMW?nnKS(zrWgyd5W=A#*!%4;- z!7t?d>5zWK&&}6aj^j~cKU$GU#I~rVi+OVnZh=kCN#_Aoip|BC}nQB;(Z=a z=tda`t@gaGicFOL^?RM7;$6=#rT~(o#qbtsVovp`k5yi4GfIU;Sg|W`8bsPJUk03Y z#52SgCeS|VxWu2t$TroVJ{~tMi0vIK%)!rEv&&<5VH4yx*+q7oin!r~<&_&-v{NSg zo#FfiDo~*TAov%k#C?EnA?SY^tGxk#7^^f2r0jt4Uf%Vz_d8z$F-7EL?!S@LCs6h! z@88E!O2m^%7Gz0YZ;1slk@O~o)q>@dc9@#RSL{rM(my964M;YWDh7?qQK_!hp2!v| zl~|YnXCQNN5{(wWkDWE!3?jJ$R=vsm%@<=~fYXKc$U1eA zNu*_tUrEplM`NSzz0#4@f+iwt#&PA&{DCSjZn z-EsS-bK!u-whguLnP7D{LeYB$k3LpROM@Maq4!akjECz{%L|wq4jz)OnT>eQ;!7>< zKbo|RPm7T^+8QVuGaQ8D&DNW@l?G|8keow+#_;bBZ3_>r)e`-eX2h$#2D-$pjdERVY0;A$^`dfgZf)Q3?OI@^+|_2Ay?)+24m97vT42ihx5s?hn1_&lCZf zP~dp)@2BP(@?L)cQb>bDU6Eu2E;nQyHzs{35LPcIOLC430HSwvjuVvrT9)kOD!rg}Oc^wKfCzgInw7GC==--^RjmniW4>|p zO9SW1#=9+sm2UQ7TsECYpVxwRX{#U77%CdpCBK||1 zI>Sn_dNIs%(u`RqpF6n=4^fCg0zH|Eg;oiyd%nDr^Y_7-ghcrFmWq{PJhV2=Rr|B? z?NQAhcq~Lo|j@4%GI7XzHo8#fgynNdW|l9af>Q zvWIsj8{xOv{aHUZTMmijMj6*gwwD-B%le9+l|SudIn4}i!lg~k3b_}GQ(fb1Chc`$ zx;W)4l@X0`Xocbn{a>O052c}hf*=Nv_a{++fxa&P;a@=T_b3fde4bDw=ASf`T-+ZA zG2$l_1S5$k$PwDS?~BJ$S;*_M5ZS;JnKb67{Uh}yV%hxONJMS#k7WuZ67dBx8qBAP zWwND$5jjui%PBQNUPm<2k0c{Tdk{Tg7)=1QMFZ_k-Por5Q*=Esf zO-{?kf{QLx9cQkCiKeCAw;5V@7GFEPV^O=f*1LE5N1nC1J`%FGj2yA$PVzi1pFoS+ zn>VreZ;#eHJznmJyPob(4r+5sa(qrbZZ9&sLP>II{2s=7mPq*Czuf-*NJOo`dUk@a zt^9(?zU}csWHx6%PUE)aKF+f|=WvJkGbb1ZG>q;-xcgc#2zG&7EsUFzMuGaK;h4;h zriUtqK(-1FD8VGh<-e(C+?K%`rLq7AqU?v?ju0q}|C%dvo%F{eQ?d8v z+0v018Wc(kC0VN2a!8X~u+ zQMFOP>KCZ~Xhq&I;{vAJ()}PG2VWA9ZyVEd6k5gfc;b5*&wG*>x#|AtABp$}KpH^*Z$zBt{lDPrqr~5% zY6Sz4sBb~qEpd3_Q6EGi2qoEedjW*+o?m^hE*|q8?=@$TtOv_xQY$)mjU*n8X9@-) zZKSaqOcgTsz111TG?fDI8IWZoVOT(AAo@=N!%>i>WR1QE%9i8)4 z4~Y?Z;X_{zRu zaFPgfzt!~F;biHErYvq-qf{)T^p>n_JL!Bn0(CREB7qVra$%C20NY#SlHlH5g4bzz z43BzW@ThPzv;7L;;vTww5h#_sNKb^N9BV(Dye@1bv!-SMF z;o*VGuJccoG%e~5S0UwPgLL%5Fw>f6>CHJsmR21~xD=Lq`9Bj3qq4CWA|aHR1t#Gp zT$z;@M5$#$ujnXp&9kXY8EaSSUT3;zBx_iU4c8)kjq6B0B(R&g+22YV-*iz2?{bD} zK+*=z5?cd_)pSI@ao%Ox9&+9?e}y4#%J5qn0p>_altD}aH&Kxnf+r>0Svq@tT=aqq zcq8?Vt`kO<8iVxS+q8}1TV@&PN4WPoK-C0yg!q|))$|;;pYKMmCukE! zEh2@rP_9Nfx|Y|o63_?pi*1nFRmZEaBx#Cr@U!Yg{yO@IP?MtM@1qY*X$txOjZ6go z%lQgA`nc?5LB}X;~~oEPtz7V>UgPaKBW`!VA=ZKD5=JBwQ!&s3Z6vcVTNLQxRbyHJX{^c{{Esw)BQX@MFQoX5d{a*3Wy4!k-!^Su7$Ni1Y zvitj#@Zwp&5%Ur?nWWAoOus8cGa~z(R`7e@1UM|hz{w4Z_Dr$JT#Z6_spcgC{K8Z#dY@;pDI7%cA2K5) zXB+puWxEcIk^~1!m6C&n!YQL-><3MZ_2h7X4oIxc3Ku?p}9%Jn4#xM5}M{%s$Ln>%7N{YN2Gbo#{&NJwuCC+x(-JO7ryp)v5eIa zxP!$ik=lc&QW2_^)EpO#TPhn*Sboh7_hrT+T}MO@lYnY+A=0T-0Wkq(~JA5O9tY@rY(h0J~IjX@EklFVjK>1RP?t zX07kO8c5-v-<0=_B7V)V9z-%-$i~_LX1Cr-XDuVZ{e_N@LE!@a2e|b7EBF2@T%??a zSxM_d@c-B;>h^nLUhz}?8ajtcwl9GG*ZOtPlNgmb#H%!sd_0#K11i}zl=fs3qR~~T z*-}oI2uDk0OQD<324$zwc_B4W%0l$}fDNZCfVq0P)@NfXXsEfEc7$o%16VH8__@#9 zdo1<1x5WWwUeptZdA!pbW9=6`OU-tV%iEVP6)g@DanU2fR16O+CS!TDR1+PJjyk~u z5t54pZ8ys^)C3t#?b9q;OD*IOneg{^y(`&#`Bjy-j+g80$)8l7J)4vPy2v5|avR(d z`2y*48w`YPdA z+BFy<*Y_oVUfuRs0K933SPUc#K%~PZ0M^emEkNVV64?59Iauo<7S7Okb5Sr)nty1z zTY;*5ncJ$TQ0sAq(HJcyxhcY`I&q9AFHNC8$-_Na1gv#Qf&U&}I&Pc*B6#2173%~_ zQCO*sL*#U5b5qp((>J|QJT!>>h&Tsylw~tk^0j51hte|tyUx;o02eyCBu5CHrv78& zO9mvEzxMTlOnroVb`?j&5~xIw4M)RNF&e2@$tgZ8Rjrt~-LP8w<_Ow9DmMZ$WvYd@ zis7*tB-8Cy;wv$FXLzR65^p$IZgr5M#Q?6+z#_AN;DN2d*u(>uf&D**%pE%6THo6_ z)RkDpey4NGNzul}C2Gl>EK&AG(tsAQZB4wkmO-N@-2OUQivz8>+>J!{UiLp{^kF?w z`=&gr8v#;*O?jGWC2*{u{ffc8Y!~!1CCjc0Zi16pdqR96uEiwVyAPwp+~ul1+%hkResIOqSQEi~^u_J>)&N&&J@ z7o^{yQ`E;HDxa>8)E|vyF$s)jA?AT+d>K9IbVeJD#&X{UQbqA59V-?}W?F1`ut8Kx zh00Nj-EYi*Rc3R-#$oSIg=k==E&^Mgg|b|T#i2UAme z>c!+HyH?6fcO8>OdY4Dx&T9R)k6FdW>l`zo8xDmhOGHlJ-MREwk4%;_{nrt>vpfN? z`Z~^0oCu@_`tICBCc}+X86gCljj3)V0i|(fJjrj?!{xC;Gxf;Z?svm4e{hoftFIgr zMqS1);l!pr+>^(I+BfWZbK>EVCRibA5GQ`%eJIlE>1p0qjn;5KaLuJ`N|T`Qcu)`h z&Pf6CHpwW{$RMXoCyQom(uIrnT%B(lQpwie0{x#WnSxSUXT@!))173X){~K0KV+&^m(}Jp&ciND0uQXed zg$-{bM34%xscsCMaVr6;E@51GS4mV^E+K`5-6_sUF2G%f+NpJ3VRqOK($@|}I%>M^ z6;0Xd4oE$c8h(3L{x`Z0_XpiqgyJUm@0!da&ooD zhIAH+`BLQ)*soGe=RGMh-thNGs%FdipuG&yvxWodCf4GvY+hiMUb$2Ab3gLj#b%c; z#-57S68TQA$K92x%*y^^0}+WxiVT+h!4xJO`K232Ks0aMS)pAh#iS5_hJoO3R0hDeN&^pgm?J}!n3N03({y2Us&6Jo$PBZ|4(0q}FC@p?TqAxkjg=G^7!ylVet7Wx7GHr%u>^Nl@}w&eij0y`)8?dt+sI85!~cF-o_};ha{@F?WT}U zwutTsjW25LilmDsgHNP z@A?I9wnLexuW)62yUvhlUc3Q&p1JZ5@qg8)&7oKg{r|-38w_Hn;aX(@05Oi?A6S(P zd&>^1FoGu7naW}i@$nD-6o9Hxh4PgZJe7+0a?v5#a4Z_b$I0~bey*e!x--7zgx+!+ zO_5BdvU+5vfnv2hqH;xve5x)x%^?|an|`^*XwQ(r61#l0QE;s-cvPlpE8fX9W#CNZ zn{K`@hCB*G3$;O0Xm_uw%mc$lg%-(CG(&5h>6i%u-(aQ-scC8A=b^Vz^*ehZCHWAr z*F(i|FjT`=R%dWIT~QHPt1AC)qXrl#dR~jps#n?evD9mP>v1vH1SrCf`9<(3yQ7v2 zdEp>t-?14Pm%qFDg#GL1Akq&im6#2B*V~H?WmAb~6Y6VW*2El-`-4zbG0FJBO!KT@ z3^{+pTCq5hR#r>`i}zyc1ZF5BLt3^tE~)vF=%}C#7t)y09e<~6w|p%!hy+giem-3D@nWEcGYA5;aU$2b>X1QIB>w37dCvS%eWCf*h>INka*AKR0{f zI(C{25t^&za*?=@vA<0!<#R0I^hoDikX*4T%+^^Ktm|}gux3?T${qaj`800@S(uSz zBgod8Xg3Qhv2oR%*Sm0-Sn3nyK93QyAW!0+j_z!BlPsrNx^G7IanKWo>j{{k)6rnV zCCX#tIoYc2Oz6&yRgXU~t6Ied9{VrGr#}>Hw*NKO$ohj|SWumY6%7PJu%YBjqn5lU z2EezVHBxsVlE7l5`2`VRAQnoeb?T&{44%s6Hn-_-VL6&Cr1yl?;Y$FE#UaK^{k~5q zTL_cW3qWDPDubdgNtY;+#Zo?0rxOyMlICJ6+@wFy3ukd_)z`+?z3beb zYQEKq3{#I8#cgHKr6JG8LD!gQ0d^8D_9tLFE% zwq(nH2Q75jOWd3DgJ-5ULcY*kK82);(@82kva$u6gNm@49qa9`hSS^{U=!am$cTO=gGgMwJgl^(5Wm4L0=z(wetIP z#R;A5VUhGTj}F|l1AJlgmZfIUixstdc1KnlS6$4ta?(j%FM^D1oK0Oib=uS7)?=hg z;-~1i4h>xD_zgS#HY|bJVz(g1mhZd#C0)_(#w(%xCR(Z;^Hn3n;>x@ojL8!gcr3bA zJ%it(SRPX^v!>97wbWmcm}m^I#&jGG>f7Tij!(!os%A<#(^HP08kFcbqTsj#74}Ek zulq-5vd{y0W4ReSEHh4YK<8AL9JPa=iX9U^7M^Dg(W>Fr4gVequK{7Q|E?Kh&ed5B zJ_Ntv?6(YEX@uU)FtYE_vXsJ$Nz@(lHtct}Z6WJ^ne{%}P_A#d+jg8ncH6$0zWBBr z`Es#8A!B%1xrQrzgE!*?3*g)IV&*SB$uLRPJHo>lWype87FYZ$T}y|;>+^pOFR|AO z)A<8(*pwC(W~@73V{Z8Vh~`uHc@T43oG-sO=!3#5;XFw3Kqv(dZ*(1xy;wGt2M=9l zxZZ3;?z2C<_c5EFM4Z#-Gc*Yf>A(8#XFgL&~RL0Oir7RWhbjl>zfy28&m!0fYh2mB}cPreYQM4nEr{| zZ@YI%jxbA`PP@=agqey+=g~SePEq8M7vhQ-UyZjw~bN%l2`p#Ci zF6Zx^1klNnjuricIF?}pq8YwNDOR%z010(C4}{8uwd0O)8oU~agCwr6gtco7v?Y4R zKn){+S0xHZ0}ba!5Y^IX^AzT{5KEJ`sjYn;585+SI&Q_v^x*p6OU-7SV7saG9xU2_ zUX@64UmIgSPI z@+qr5hqug{b?zcr)#Qj3rJ0r(sw@_v*OsnH)G{4mG;kxjF8c0;bE?#xjkIJ7C&^}> z)i15K5qquN0MA=#?Wrn+c2S4cH79G4lp*D$2sWY{Fye+?i*bba}!JPf~Jqpi!J~(FgPCXaYen-60RKlUcdJ zcA{rjb+>L!sc{F$BOb=!{6+5WI$)Z(U1&q;HVu=(m^U!@}PAZjBbTlcQjchcO37QJl__jZui)kr^`6j+ZF@@Eij*+Ip ze6mo%n+a}}!^E#dA>SpVt$}U?pwU+)Gs;=C6stcFvY`pw*9d#H07+iuI$jHhJ(#St zgr;#i+>b5~B7c+%<-Y9`KJRy<*6u~FM5XXlw(s*DAdHE=k7Y6jhmh=zpVq3Ig3>9U zwK^Z!`>H9~$rimDIM@N%{QSlfPbBP1_y%hX9zWSG7h0I_Ko@u|#);EL{QZz?0~_d*Sc#n@QY>-i@e=ke{ItrCx)syngBKYV$3 zXd?0TOQ$CAg4uV~_OB$8h;!R>r+goTdrG|%gt6&t5CZ4XyrYB4`pOUr1aU)2s+^Xr zF!U;(nLwthTdfGX(dB~3=AN*^(5&oZ@|Yips`<{iA&vy`-n0^WQeC_}6p1LL>R9YM zAEB*v|FiM&f7oYqDaeEEVh(qVts!4@oD&#dhPTt`$_~)9O=qNXv9vfC%V+JE7cJjxMobXwi+S603tNmg50CJ)zjdAn;n;&M_S$rHF? zB4TQE-xy^OF`+Yu9TBd>gIA!skUsk3{bE7*wg%_H>RZ}YvU20U5+6G#Nc{diNdC+u z1OmvQ^&V(n`=G{=ML#Z@!9YazY54jd;$8>|HIfY8A9pOMjYijp>kR#pnDlzHpqYf; z3@%%_dC7UGNI~xp#*}KHnJr;Wrn5f9gs5gHX(&~CG@kWUNWZf3K51l-s`-ErQ)${% zDc&FiSLH12st?R3LA1G0Pi2}8AaPW>ps20h%5Y(%O6E^t@iTluX;!6caOi17i)2-1 zXl2-q!RFnAdweIjKbg}P0-w#nJTP0LsAnR{;$)Ki`sHLX+r9q03Uh07Fx%6$cD&YC z1S`A6{VZ%8>2lFKtNLo*K3D4= ztD1-l;ta*89T`7qo~RRXAr*o%Z5B@Q8By^eaJ zhA(|ESkr8}k$m~={1A|mzANq4M*J8m(TOl`!U;Uz9E9_+xbi0(y8k}fuG0>I5}$Rp z0+wsAjZaKU2gzu#dj`1^4D5yN&`06B9h)883F16Ka0NrmU#(Gf04X#T;QO~!z`rT5 z!GleE^Wjfx)MDK%j!ZP>4{P*fx==g;dO2j=>}vmy0vlAT6D6qE^TB)(nz}KCHY7t+ zH>=P)Aq5iN_#5dBW#h%-(A(^Y&Jb0IbhU+SI_KB^N_}2@tb5K1jbtqP936T##C38Z>Uq)@?L;0|S`GO^V(f(U%qfZUz z3Bhm0Yx*|)hS>Iz^%cPP|FHMgK~?W<`{)vp1_kNvX3>pGNG(d~?nY7?3F%Jh?(S}+ zTSe*a?h;fu--Yh|xSx8T=l7mDbLPyM{pTKLji2v*Uw2>E_Z}Qlm3|rDrDq6yUq5)$ zF83viqhG^!cs!P$n(*VmGRSyCAUu^BKqe~w*cWpjCq0NZ+%P)m5w-!qV$+*I9wsp6 ztQ*01Ftr*f0+;wWN@C2EQev1gaV;8#3mB=s2@~vM-dR0!p2Q4Ht9&3>gOL{>~1%XV>>T( z=$`aT3+1}R8r2>gB$GxH%@^6kp5+lNcHrANX9>cc@Z;!gIC5vmk`wc!_Y(N*9S)L( zNHh8)&JROCd@Fs!PD^*!TiUI3SR<++- zL@{~BwU;=(HkYb_Q-<8)BC@P?5A)j_XExil=6H*_w6R8~APp(m+xX!EdWnVB050wQ*aIoJ4>GM{%;_e%%)2I$Mv)MuG=3_Td=YgXYR=jtWw zg7IW}F?crRzj!w-85h(xlm+a!a_zJ>&iHFsy&j!Odw$WIpKSYtTxG)p&bxTKb>(He zaaVCqL%IjL{uy1*n5EjH%T{6EqF9DIzD`m=*c+1aYqjm;{JAPqTy}Z=S1S_md<12R z*oY;EA@Dd)EIVrk;>moQ9Or8C$#$g3ePtDt%JaFHx5-2IAj5RBA~@5`&AB@Q>n$ob z{6=rJn#~Vq@Z8)ei!@}XjqBu|NiEK3xe_GOi#kwnQ=57e7je8#tCi%Dt0AY%FM%um z{kVk=@R$1k(O)nreo>(TXYd)S53>h??u&Zg`AY=Q!Ah2_-jIC9E#3wlg!TbT%y2!l zM;oH)5;62l^a=$EN!a4}Pnv3qlp;ZC=1jb`#e>DVUEtxSak?JQ+Zs1fdpdF>ZM~BUie&*k%7{Cn6vH|oa!^81nFg_%{*Nn?HDG1l+HTo zu5|gVa>{D0Ol-t5;8+~+)64dCy;Zp-iQqS-nIFcqX5N_l_9F7Za`kGx4e}uLQByS@G9*U>hxLI11LvnVz)mM$cyEHU7_gma zEjiXeX)lAX^75UjA3G3Eo(39eeVm@6iX0p%AdS@y!^`kQ1e;7JzPf_XNW!mbG%_F^ z`@dtL<2!#lKvF_5kf;>3^vRVV6g>`3H?4`yK{dtVK{7_UQKf20<)dCIhWIkBZ>rBjhRidA)nOL!mR9Yw)`yfgBMcXz*ymVUdt5BS6 z9F3Qp>VZW~n5nAe(O;3cwTk*{{o~#~&Q#S)z+@IUa=3WlPvZ30`IQ{@3{1ekVX zyDRm{iQ?IFD@Fap0tOuubvyBqbSJ8oDs$u)M(S0aJ9tyT=Dvfq48xfUw#qf;Si8?l@mhRRPaVb_Y`67L*6<~@60nC zF=-|n42;$`SA!S3wBO%6U{tA4>U3fyPy3G9pM>sl+#+3;NBhs;>d8jQ{!tJ6A*j?8VJfPLw z5w`Qa*~UwstbFC$CrBN8wgU_wisY_ap9pOw1ohRGX?(jbp`YK)|5{J(aPl_Re?d)P zyl2j1GzwFhW{j){#r+(sSIY^33ui$Q1#*f1YS~vI!OnSIW!b4y&wkE;!wKWOn9^6hm$tR+D1g6B6wND!ix(y9>V%>6 z(zs9hEt#-#ZiFga5TTHw$9A@&QmW~qdw$|}nvo<@L+o3ICbM<5Bvv1Nk5|N|n;r&w zwRx{#Z_NJX1@~V{@PAlK`^#yh(776QIfoWqNjxVu;+}A@UL$5|3sJFtP(Lbda`nq) z>;(5=u#{!h3nXLZI)?*Sj5jMrVw2@A+Yqb9>Da`q(z#BoO{)~Vg58J{hv#dUCLvy=)%*! ztS}}zC^-IDqa1ql0nlZ)EkS)qW7ml{iOd|Xf3WK?EVr3_kwAs~X1AS7fk`i>35GDo z(RPSShQ;2&t$BUiIE27Ba)2|ew!sw6gMHMGA34A6Otzo7mQ4QLW}C*Sjth9R$ zzmQdQVS~Do5KM;TmkpVeC+s_lcu-fO55j(6b7nf4%I9?Q1);WhGF&78QYu-y^D<8D zll=F=I!ob7gMlQ@Vh*OscUGrOsdy>}bIFdi)ZE_y~hi-o0d_CytjPyAXO>sV+ zuF+r;TOd4T(a(-62bX?Js5XnFq;pC#y*kkyOOhK}*mBu35AIP9(bizu-CIPpkcv%k z)3+LOPBaDst|YW<7_$Cd1?6mUULY1MchKS{HW*t7bE~VYbv$RI&R*p7eWv;KAQx5$ z_cNf1I_!Kuonu>C@%8_c-urox) zBp8J{=kc~oTP~1NlPwBe7ORwZB*-8`dKQ4(Y%dpeskV9ZT3l6}#X;~^Z_z>1+|KlF z^JFDKd1+nc#B%HM3Vm!4h_HSt8ScveP_gHI0;Tn!A3eLueKTXdiziYp*76VT~+9WH4$j#Q*|4&nDw$8eD|* z;|>@nMuQYP{3l8sFk%BGwX)x8nY9HLt}VYnJ0Zf44sO06(cv1zKHY2Wb8j#`<_8^a~9SkAB{B6nz^_Sm{ z0e&z0MSeE6Dzmx+pjY|*wg%7N-rlg@f3&1O5P|(5X|EsZFR=XM#W<{n62|0maRR(i z`2(>mK1f8acGNN;E)h5cvtxZoI%NBL=;%@#D?`6H?*#NGDcUz(?^@)$R%t!jwM)Z(aG(0p1^NbRekc-)%ti5ShC9%=eS$5?XAHBE4k_k4B`=gRYhgRR*RwmUXDYVjR z99`4+t()@&Qm^0aPQ^N^JMmXeE_k?|U#hUK(a|Ir2W-D1wnw1OTk_txcQk8ozl?*- z59`EXSsEyU$b79(G1U~ws1ZnlFh<}KwHd0W$TgQ+B^H$n#+|eMm`7_?jh~c#rO@wv z&%O5SdVXUriX5(S%~cK$F*lGm*hyQyi`RuJlF!OT-Qeq7@EdQY@W> ziiTEf5J8Hqc_St}J=f)Oj58!)PKi@Y!YJckkca$Rf64ki^oUp=3`QlJTqmJBbs%YA zX*lBVzKBAn4|(JV&o`T&{s}VlDtN3;nJRF4#tgS^T3e&ElEZPDsX^I)ccW(Yy6GUj z6{%V4Eu6R1fxE0raZ5K0V4H?@^+XX|dFv%iiq-p(YiDpRz>mAtiE@9av>Usg zfw}wmgx?nOUjGeC#=Lnl>i|{pSIsKAXWt%sFwy*Owi1BZ{)KT!7ie5T>6Y&}Z&3LZ z`%5xK1K_d5=2RbbJTtx(4*tG*OfK>kl@~J1Qk z>`cHbylH`OpKL_)^VfgD#qSXMM92F1!HZBv%kkpJS!Y+SEOK4XrRZ;p6)J}(<7DvL zwk!1|3izJYJML>Z=`BU0U*|Hqn;E>#VP`fDh2UPuP5YBQrefx?9$tTy+5G)xp7ncE z+ID`eXS&PH(0buGi3d5W0+GcxbWGwmCqG_iI3OZ5WH_tSUFh1Ci28o?N^;+bwdb(x zUsALg5dEyVHBG6g+4j1aqKE;T4JrRcp^`g)CS%)wfRD) zvR&Vknu#u+c|KTlD9aBY(`&gLA>>{pp=16^13tex=GO-8{6SKKs_~$B^3`BJR8KH= zb?sV~I;%19+{fe94{V~NhOIGqy)!iyPGy5lMp6SUk`zC*VvcM+iqSk~a*tv0YW1g( zD=R*=6B|h`e`Y8?r^Vv@zAnJ+U@f*;D);?J(Fg4-_b;E3IX`Uf-Y|NUx$gJrxW`+H z%__o-DyeAuFvVtg+t^aYiflh=P=0fjTKCcq5z>HVAnabZ=wSUm;Ir9Yq2r=;L8=5< z2s$Jo8uEJ|3J-XAE?^GvC(Yhp$mH%58unIX3BLuAo7*ES>GXM$im)M@94`rm5b%1S z3{+8x1Yt-e4Hq2i4kdF-aslih`r^hsKEZPXr|Tja!ZF^Is$aGwb6?Png-&zm2^FZy z=$Du~>_SR-2wY3~Ca9+}^b4aOyePL6j_bMU`9aUYq>_|6(aiT+WH$HUv22M#fkI^_9!!Q0N$TtvEjzKaQx)6~A)>Ug(;qSijF^x*p$?`=m z7HF#1^BOK-uO_;VW_mfqDK4`A4xdxFw={Lak1nppv>@KX;K07QdeIfFK2I81)7g0C z)sHbTExd9_kkEZ;r!uu=$DIJG0G0OHWH)o)(bG=OC)(Lpmx=Jg4~sFMe&3PXo!tyi zr|q?~-9b4nz#i#$9}n_s>jh~~FgA^TOW<*aSO6ivvF6u@ zf&)I}{L$b0*bE^)NNQDv7xG5JiHsIjEp+T4nN(8ri{}V6Ssy)-JUi{pYN)z%5f$J% zrtP*Rq7+iu&P-XeM*=Wj%2U#x(@ln;4k!bMD8(w3#Peu|%@vP@sti8M0wj{Jp0`Nj zT!bMh?f1UFw})?p6l1B;C3?tbMS!Y8xPagCf$qUR!p&F`1R-0v!6AqP#)E5qcVFfD!{bLc} z-qNGR)OPK85DkHqB5u^Whz~RB@1w{=U|aeg@E-^P7IYu>w`-mM|9||y=t)4(JN6f# zqq`492wF${r;-r*onC)jklg)&Ebs>pfG;Zpn*Zm2@M{DI9W(@hgrVnFz$QGDpA8r^ z0JW>ZV2b49^**SE1kgAI1`UEfaHt5sc!%zOK??W1|&|i2+jtL!Q_*1?dB%}pK8F#-Bq>x+%`~ngY7fL63rED`tj!M@Os<4s zGJ6G|fsJ78k*3<+$!xEIG^S=ws7l2UwQKFALb@narQ%(ot!0~~zxtml6~vI-!L5mE zi%BcnYCxre01n_@CA)%s06aGILrDOyf`0cZ|LQ{tJKfblciJ7$Gq0PlJNIJDhz|CG|y4q&7N@-Recoo}Py4kx|dGo=X;O()9`;huB>bNRa`y={f(%$f%u6kh&4VBU%k zyW`s`!{?yCnm4dK{)c(Xr8OHO5&_qQpE4Pp=#+wwO$IZ>v&9}X*~dT6SFIL~9mFyl zDpF?Vo1cj-ma9OICR0 z5Sz)oRsrLLLB}xlJBgG%2XCz%ySB0Gi+dd9a1U&i~^zBFA9yzdQ2qyQ7A-z8Fj9SVc6POSXZ@Gi1H>6Gql zT^RTXME~|9hz3uEo6Yq{QPe>{LbqdOj-(SF{~s6=5tf38k=63^BPir^8371@Ra6Sq zsi{5J9EA4Aq&?A~2msi6HNDi}IPI5YP-ifaR9(q`jsPuA@g;W%fYP{EHWV+#l{eh@ zT5C9wneAY=p?bUDMCfoVwEk@Svy)P_qg3_9@U*d3`-QY}ooQ>6lfn&(t0N>qE9Ui& zCi|MxO`lw2zkkrFDfv^U=9#Ae^-xot_zKs zdu)S0b!t%1^6-rdWg3t{3?ubv`hEQvgFkg@NHL6;{TkH*Ga>j^fvN$Ny|mdu^m#mb z{_TxC_@QhUxLM)9lZE1`x*ZgL!Iq)Iqy0q|ssw|(6er@~urB%cWT8oamS1-t@EPy{ zDgNCD)E9R7D_H#zB(6SX{R$G*c|xGyf&>8JfEWFQaLn0C0K&z3#A?lzK+1(}hJ#A^ z3Wd5|ko`f9;^`8NW^;vJ;3l_zW@RuIS=UN44tJo)eW;#Urxmh~R2QN`y!3Yv{u@}C z^fem>-GS970jEOcRAuX}&lP&?S|c;-CS~OYyJGV(7iAL-PRQ}&m=eNG$1U=7~= zwd%y(v>$U^qviV55%VtC8q2dwT{vH~cI&?{rux(d0Zh{WRA?wnFMr<4$iWHQ9t1Z& z>0}sXvfwkw607Zsa-A~_&NjRg8Y);e=J|$)$Ut_Xpc+0mKy>^4V^TswvqPI3NEbFTVTG0>Fo+`>&$XA0PT} z*+4a=*B@{R%?5t^(088tD^^22^^aH`pidwb$LLjMpyfXvw4ZPntKFL~7-yP|#_h&? z>#cP_9#`s^syKk_-^FSk+xd>j`w!z(8vZdVaeUOOlD~`9JE_h3eG}g>YjueZu+;)^4e{8I;b4FSMSdqE;_B;63H#Bo}TJF z1iLeEP7CyG+vT;Lbp+S7>=Yfqpfj0?#X_AU5^(>>5JjQIim+V*#fQd@e; z9q&x_gPx>1>j%@vO(h6y@T!ipR{84xr1cF`$D+}Yd)f}S9#rp_6@aaEhuk107kW=BR+AZ6 z(F+H3=E(mn0q#tL7cdRxe}@6TC5rz+B>m4!Lx@bf$FbxN#FKJ^OQC68rQREevgJ&J z<@z=>jcX~Md53tH#=TdprGut%T|6{j=R+?oUX1eMj+Mi-$ z#s!!xr2Yt5QsluB`az_`T+41qgZ80}ncaZc7{>(ds(j~rY|ZfIy#xx7In`7agn0(g zn&LUx%C?c(fiqMWMoW~B5?AKUmKV5~l8=+=#Llso|C8~V4OL>vk;5H_DoLAlYRQG8 zv_8wt=5J?M;bxi+?d#a7qHonXX*28S;AfMA*lKCBOYp8~6WoiOO$?)|4D|v4B45m4 zin{0YENTZQxsoMyMd-20y^MfqWEz?o7O9o(?3A?#!!ne1z!7AZa;+p~m$gzCGYYpO z?UuxLPb3%#{-x630t|@rKQy3#lYdcZQ2n>q0@MNjIty?Q-cPuz18(@Slc9BhLDyF8 zq3-+OhxY*?-eNAJyNs9jRMiri@s^evOAMv*$DpBloej1Ap7Cm1u?$qi8zK&`2 zN3k#LpE@0Hb}>J7Kx=KX%^Qf7GHHuxI^S%~biD->!JIDuS-4`77WS%dms>93G@hya zQ$vNPuNNAd+C4v?Ows&S*}`Ep-xt;Glun^8t7z$NDBO0fm4 z#%LZSj7Lcf(&Q#Qr*G5>`$ZXEm~61y<1+l>z-T*9{p)sqKAXt7_-g9kD8pZmh^O0Z zP?^wV>41^66oj54Z7T&s=%un}{G90I!0t#L0n~Bk=8CLU{R%}L9k>Q^u|o1QhVeC! z2gb3&fC#W$B{?5Mspbryu~XNMJwrKK&^1Ga?6vYM****@ssfO*#eVISaq)f~o7uHy zE{Pw*LBm=c!;8EHH2AW{y}I3l<_9BxO*Yv9GvohvX7<0zRsK~7`?qHHTe&&KRA=xr zgt4lF(!OH5rzucUD(( zCyKb0rQGoa$oQYmI~#=aO*pFu%VIfaytO8xkfQy`Oi$g2z@ z(R938d#4nQv*D=17MB|*?pT-?tu7;JBxe;)M-&J4GyTO(ZyW}oqR6@vb-EEEFJ%;L z76L)$-5D8KN&$n ziFk5-mM!UK)wofv(1S>m(51fpI2G+YX`|d6PKwd1SD0a=()ek2e)+H~UTno!wAx;c z09i6)v1^_>dZU?(c@g7c95;QFVW9=RTvfui$aGKe#&X-YnYF`q&`@)kUDJTUR%UK$ zK}F{S?!BX~M>r@)-Iyw`j(f2FZ13L1PZq!~h5jE;t^QNH{Idyy&^Ab_Yf0TC0Dlw4FEdmuOI|Z1qY`xN&79!>O{^2AMJn!2 ztkbj2KHgzBFMvCJH1*r)?vw`1?fgQkfJ5GrlaYz^!keqK?a9+uhYQVPUstRFHUrNS z*-wC2XS(d!IL*A%5^4diRTF3bjBE?QCtx$A^mk&NTXEjxX|+0@w8Yhzeovv%^-ipl zqc;JIg=ZtsK#p&x-yni#qgP)6h0ipH?G@BGe<~($6)L$-z87ByE6XExm{8K^8@|)^ z=UtCg%Tu9t){vdZjhFJ@&Wlmg3R-_-I3`IIe-&HsE4AWHO(6Faxz|9Qp^4>U=p!P^ zLz(rbVuJsMQoL?jeE2!BYjV{WI<>?FoE=DZUQtX4XWfpuqToSRzd}jJcLYN@;fdbm zcG5C#Br^+19^^s}5&~vD= z++CQ*ak5(I@EJP)q0wNw)IDCyKdR|;GCh*r?g4J)+g%$fwRk2&czto0?H6>5bAg)- z)tEJSEr~Z<324mrsdy55xn3mC4=vt$2pC%4Y0S=if1b!SNC{}nB4gl^f?)9*@Vrr! z6Lf8tjQ*xEs~XQp30F51M6&|F0H(atm~Fzv38t&F#|>dY6I%t-n+F(#3ik3$hCfNd z%?aWtDj@NcKEc6pe<7wusrd}f%qU2a+ALd7X;2v758K~NPZKT9EYFwxAA~;glcl%{ zH{ITfN~ViDK>g#V&#pPhyQ2Pa%+rD9<6}_>xk@od|<5phrLDOE{EI8^@Q?XjSN}DQ93*!L4b*u82 z-y!7MN{qQ(wT#*{3xVbhZf?Y24+~3-JYRh7(?*xwN?eKw#_AS3#$C;i8$%mCxCF(v zee78&>wR{9C^pHI@u9n6^zF5_gN$A4Rgim^d+bK{AJ36T)4G0pts{iIpR0R&5*p_2 zA@(Hx6EQUt$0yFTcl)d}f?L~@uM^#B43_EHq2&3cjyl@~)fWM5-AtEr_LG*E^Uj-h z#F%UUj2IKlgP-$?0tjg;R#)o@CS_L}DNYAhn;8M%>#dv+StNW%acy3vh?;}z-9I#D zzwI|{mVG;DxjguGSp8X_m(IRe_KL!mvi$qWF!$m2(~siJKhD0WSpPVmGAaLY@#z^` z%bcldxWMIFy!Fl1R(|=-)q+ZR6H2d??9lbur1kBOuba#Q>)k`79ycJA3=lj|$Hhyq z)h$H^3{HOsocsr`7!lp|-pvjq^&@YPZ^jy>vjB?gkq;?lI$Ztx_X96kd}*aKkz%=p z@&26b+{G(g!0~PWzvKA7r|bVHF0B$T+xU89CyU!t*4^%G_j9p@^&6sZ7l(lgh_}07 zqL!=oh21eG9&N3QXFCHXPI8Oj?_cL<#~0-;Z=A2bKR}50+#R7I^@NQESO8!;FLj*Y z*i;v3v-@GZSa6MTak%cprKcL6<8k%913ITP-cw{C(%=TXAlhD9ieMKdXFY%1!Q2t3 z!cR8WvzK{cY=FW~PSmp#gpLRyE3UPu7h*0s+7BSKWM0bJYT9wiReeKI68AzvLlg@ za5DX7c+E0w@x{z?EyONz-et%lszm3+&8)@$F5GfQ1wc2rRr*$_C@aVE<<@R_+f%sV zif%N1mC7FCkiCkRY4lV1nPLR0g_3;Vlxcx<-I6wPnQlXK!5`780o31L>@}M=%hVXK z!dq6q-s^1TwOzEU+R)sxYt?L>luTC&f@eJHfW=YP*Nzy~U@@$VlQ7iIQExsn{P*g9?UJZtj>R(-KJ`xLlbe3&fd$sga&m@0nuNzpo)quEN|ovuZ0=o_=Mf(lbzih6r4N4sp_ zgL4Q|y*uk5-NRtBFIJNe>id0`3oCTp7*3qH^X({t<-6*815rarMyYJ)-IWNL-pw!$ z7;uiWENJjes+AFJ%$s=-Y^J(F9Y5acdb=RM?0To9{+Hu-v%NC-wja@*`OEP;;F-T4 zb>monKklc2IzGW||9<_@3;wg&wT16L9e>X0!;jN1QgZI+3%?xy>DP}Ta;@h(eayGt z&xSsDoP8E~==lQ>m%hF2YEIvu%YO#KKk`CINe9&n3C>X+y?qqAbdEhGIJ+|j|Gf44TSxGp#eb*2kN>}S1b>VFT5jV7Kc{yLk)?k(y&J~y`upkK{}BKGJq-Mx zY0O_L$Cstv-0r~k15AwbG#Osom=ftM;~*PdFGP9-9ePZp)g>QvNI$V3q54-+PkgI> zJwFm-Tyj^6=)mQmo!o?A7OE=KG#2b8gjFBdL0aN4&=hWV`1(}?dE^?Ri*ERHZxc#y zN&0PldK}_}aHUec*TaC&S0WXcrsFgfNZW2($x_)I5c*Otx>y5KiG4}p8teubL0+31 zY^FNFc;%-)8;7F-s&+_z5``;|VT^1WE>%q6!PHVjSU9{{&WdCZrBic%*3VtNyx@KE zq5=btxb6IctfJ|HoF?`R`GwTmq@9usaPJN{*N&Q@w0dXITp=JfXrsc68hfL%pE$X= zwB-bUr(El8okewe8Iq-eCsNUVM$rEDe*MCQuZOsG!Hz&g!`NQTz+_Oo?Lz-r^>?48^dj}t%<1j7viFv|Vw{+3h*^Fgi zy{f2tp<;PHu4+>1VE$Qtwy-u^zm~ICJKy|N$sk6{u{Lp@-q8qEj`4Etkq_KaTgW`> za65?ombyaj;0NK^Ql@X*aSva0O2c62af_0h_hYo0WkTk()9PU6jRxhnA&f2`$CSf) zSF?4}rZ&`aOZhys%9)U-N-qQ)cP-LU*BC7|+O1j7+A2Yzk#ANX8a?`>3IX`~fKe`h zLK*)ag;f4eQ0Tq(e~&^HiGPPe|73^YCko-9b^NDe+`HakOT+PMf6QG|=dO58|Az_U z?Vl4w=m5%X4zw_IN$mN@w7k6?umQNcF)nmkP7PEcz_fhH=aCrgGC&3Ucg6Ev?=V4| zpBlR$oNqhlGg>g+P5nwJV<)bG$GE-NYA|@gS%{Rs4Fql0RKuyl&FfJd@yp9kPiq97|plSJ41ba$y5v zK8szJT3+hr$Q4b-IwHg%)z{x-D^!`9ej!U>!heJnkQ*$_oiZ#c%)9q0sgVDtikyGb zTuwZoBA46mvQw0wDRk>(l*t?NCu&-ao!g@ z{gf60EM{05-w#djl0y&M=-E+hI>7COUaWoe_h+gEE*W1n3c@p;0Vrg7_DO;!aHmMR z`WkD#ZfcsR?T zK7YOt<^(E&+{*0uLE-NwJ-=_e|0URUa{g=AoBW;20x#t7uj}y)ZS`HrpF^A$W0HgQ zmJ;HvoX75xkwd2Wv)zKQSM0laK{6Lp1;?R}_V22Y4wZPj;iJ)4)>~PRp9mbI5-_uz zh%tX?VH_0+{oY+XQ2J!9&LPafbm4xN!(^8G{%4;&lQ!#3#_GfAmF%}@?mpWT9t7W0 z_|u-PWet!t`J7klSRQTi{=ka#%s5_L^Pc4Qtrd42E?zjV=u5?^H5I*lOM1*AR=sPM zPqfV<@4HI>fBhoVr^ zahOeLHsK}|g^t6WhqH+<0TjAEj_^V;%rdM96UIM5x0T2t#~J7s;{#AAG>4K#asZ-! z5}h!dL(Q!=AdWj0$ws%HtFPDfpjjt%D|wKtKGXyLMl29$szTblemWAb%tkn z5c$w(>_(J4mHA^0jo5PsMyy<`rt??!iytu4mb#sD%>Zkg@2bvm9EPLWs)X zSX|RtE=yRUvu2u*x7EFUvxo+>T zAz#iw7$JYsuWhi0H{bG+y`Dv|Lbt)#slAdMtuCPC+b;u0_wH5XpA`VRT25f284l>C zhR}>&FgtWt3kwblAK26=G1yPh8k*Qrb~BtEO#L>NIA3Icx`Sml89vkMbzg&$_Rl8e zzuQXU_~5uNUEEtx=FntcpfVIb)l}CsS!uG1ty+pNJX@x4sGVBWz@pcR3e(Q?#(8_? zqXN+-k**8hW_PyKr6rNu)+$1+)NMK1_omCyrN_ZIVheRwr#X{O0VF!j6<24X0ArY^ z9sS#$c{?eudIZ=7k2=oDbc5Rmf~0TZsseN^51FQ>eaqCo;`#5;7U&rhDt{$2eysd@ zj+HjAfIN7rW-BY?UdvP#|4+)1iLaPk3>RAl5n= zMj&}%x(`2PT~(jvhQ;XmBj&wSic_PCH_hYKrH2ti$Z+3($wO{vQHR%IyW5kvoDx^s zN96hD+JwXoW*LVTP{a{WO&hMP31R%%q!df~2u{#9U(4f;J~PeD@J@P}mt<#NBr!l_ zm>NLkj=xhJM}PZ#2b`CNA6;D0hBQ`EYlkmy-2sQZ7t(4q^Qf#bIQUU{5B9cMRYf?& zym}O=do^OJi1wAWv3lZ0y&AFlmw5fSSwpLppWU82oJ~Hcot|)$78BVBL9OM5zyT@M zEdg}{><|S;;|6t!wAj3(21^4fv_*B-JjYc*QRukG%wdst?`uDE_!+b(^|MKtPx!en z!4>6o|C8`Jx;NDIC8wjz9~c>i$!ALpJa`XZ)eN${ZwYCU=H5U1{DS#;dFzzeyYi1B z;#%mPNbv+wT@UjM&!-IIErD*2hA(4H3?!Luf+NqJZZ`9Pk7>@1S*pGYhqWuDR+I34 z%ZsI3G}*7h_XEO=Juyt)RL+wO5ng?WVZc0FB8CJEgS z-oj!Zf$LzK=Fd8x__Dnr3*MO*>Xvq;t@Vsn@xhG-P5ISxnr(;kyrsDe6XC}lWbf!T z20jxBoPLp&IS-!dE;zho0%N)fe<1mg9Mmb;2cFd8FGP(+?R&T`9L#L>=&bJ8Ki{z- z-tXBVHHO^n@Jai`T#)A;qL&vbM@IqX3nKXExsiJm_$}20CvB!D-UGYr38H`maOO8>>x1T!LU&Udf$o zelEakdYtqr(V{+3VJL278DU^@bk8PjM1xCmmM|rEPiF4Y8m%&fAz!ok>SQy`;$eWS zJKM?56b|z6=#RtmgQd-zTL^KRz~{q_&)l^#+O6N>I~Ip7&Av%|yZXvMv6$BWOkznm z_p>bj4OT(ai;lwV48CmyiHx_8_+Uvrk-<|-Ug*ZAkuMq%DWo~aaTPPYVayYjEgW;Q zvVw`dB|ZkCJT=w#q{XgT31&irHQ;04z)`V6obT5UyhzWTfZz8-W6YLGwx8 zbdiIC^z?Y9aWV^PnW3&v`)IU1;aIjZq{Yk%{DS1`x7;<`@Jw>MwaoMLD98uR@{vk{ z3d1s#6E+KaY%BUmJm1{fcF_VVybML$2QVvTC{Nb`6<%|{5!Rn7yx2pST*F+ud(~4Q zhW#3XdrO10Wy9vXb+AtgcgslgR>y%VPO40KhBh18#oawAw4!c2)&u?B1fxAjhm3iuL^@aG!`CgAaFAjY)+Pu}mE-r#2b0#Li zfO@LTqU@eo0L!^wGXf{d#92#h*2+1^z51PV>K;n+-i!qa?EdVCvP_nbwr%J^v-75V zWb2y`x5Y(1j+X%rzsVah7mi%44ywa)&zVT=>a-<9%)V@LaT+}kb-zr#+M=NY=Ipb1 zWv)BS_g1fW%V=Qv_YjqcUu8kFu%BJrmM&lWAw<*0$oy*MOKga@j7 z%nn9P4!=qD9+Lk!3JqYs`MMTQ615un?B>z>_+z6Ru@tw1E0L_2@T+fMH}9&r#dlK% z>}u2M6HhO%zgo& z%E;!w5sxVbvingEy?yxQ@kNceNI=e!>1Pc!w1+2vfUvng$FR0Y_6u7PBJYO*;%j78 zx;*rxaK|pNLVlR}2=Bk36bP}XLtwCYI#SeL*z9+#1U@>cPJ6}bg+iI}aQ$&FBR1@F zV)KMxFT37K2UfE>5uNKuzpxsagNR|_1svwFURE^NaJv@tgcX{0Co>9AX2@C#28OV^ z8YPiciGM(vqG*qikb7Sz+u^tdOW#xptFNrZDY}I4^3h}c*?qdh zt;YavY2D#g1Okd+#XrqQ5U9)u1OMETK8YXDi4Kqam5(6bG>I!v1SCKg4}(r~1SLVv z(0w%8=V1g9Hjy+RNWC(|fZg#X3_5wVgE@3q!N>ID!0tF#P0_pi6D0=?V=bFXCA0O4 zLv}WGWFYlFL9Wi`KJvu&aJrtGLn504Hb_v1-xFRc?fY1oo+rVLWdp$-+C5bumf>4# z9|CdQZ$Rd&*&3@bkP~pnJ@y}0zdwbDs#@rwd8%~DdkAMF@b|H|bQS48y(5K3erl?xiaw^esDR^$JBiLdACne92{Brf4b_#A&b!w=inG}#7Rv|{6!bF$?+flgVN^A5w_ zj4vr}D}p_02U|S@DeRW7Ff%`ICi7XU7*g6307;RBe26J6ph#L=ie|-KM6^49VF7wi z&he_UkGy!%GJ2=?0ZzRThh^Z{T#5p2X)NTD6KQ=mzOWH3ARn<; z=07K_!K{KT2ZL1?TOx-nPjbT8bOV?!rVInL-f;obr;C{x+6|!Y>uUWxX|PDRtsp0~ z$57D|eLGxP$=@ZQT}-*lbX?=LXjZ;7ydMVctAQJJUj1N|3eL=fJiT(rq+9`}Pj2Ce z)S15CLqHSS>La+M`sQp`HUvojY9_6K>CpZOG3#N=AuICZ!L3}H!ynuA6ox;}%ZHx+xLVfXczRX&nDYGN(ZjIFv9n1} zj&I1R*BcvHpR_J+jYJS;;Uqe0diK3!DivEV`r0vS>Ev9^Ghk^X-b1HPxZkI~t@H_{ z>vema87zKg+j?|+@5ooTOX41UUS%h=z0) z&g9qb_!pJIh%OX(8u6kW(MNZ6Uti68wBCp0=a2QiU6`Uj&U)nah%5scCs9!NkGiih zdMopxd-G~4X|mYBy4Feb_~$ih-p`W9?ievUkJoA6;$)Luvyh1z8X}`(ix2{JAGs|R z%SL~b-xu51#!76QX^G*ee%5e3#eQZLm*<=qufuu?-*Nc8Mb_>_CmSN9>h!-FX4Zzq zT0+^pgh(c`G;Yh2Rj$#!jvtt~7ZW?dX2SO|C{kGFvB{&Cn|z-qZATaGJyzRKpvgkh z{~&}a<^C;4n|_|I|LHZW=@bG8fd>DRZwq?@FCy)e`!7EF4E9F`5GHfMRCGp%bC6Y~ z7|FuA(s(O&Wgt;(>Z%S>ha+`mv!&AUS@Y4GqIcW)QfSJC2!G}j+RgX`Q`GLO9_jU$ zs_<_pJdY?KT%qgr8yVT1LhR4g&v)=%J~l?ftgRV$$~)l^G_kCUmXpxc{mm?b%z<)MTym?aEs zFLsj~;aQEn@#1O_hhszOejoO>T((U>1Wdp++{UC{=~TWfg3K+~?tFb#z29Gw zdc*$}RD5-+>JBUGlx}jdw~3;7(|F&@xo$*d$=B~*2FSoMus(yxUGKrTNxG!?a$rJi zuh0v;8w_k^)3;mF{*=9{34*Fd2)H1p+U{|0jKQr{)dOc(`QUa~8!VM4Hw9~oLf484 zAYr`ev3F9+W^s`k)3CT9dTQJ2s%ny1tLQ@WtIP4G^5+=QrXz}qNjCJk6!4=C_F2;Q zy@mNNM{8icRCu29C`7wqL*&y#ul$lST<~{HAuk*PXR;h0J>SYsfPBGqCL!`y&dV_V zGFq^&YnGEA?_WeOyi-$zCQasYd%aOq!?$Ms(#4XKMtM6_eYYGziJ~NuoTvszy{srk zwtOE{Y)=2NE@vE_Co6VBXrQjCqZ2Bc2ob(a56O)BXLa!m@_l&RGIU-C? zZTUW1z>htCFYx-)1L834v3s;Oq@uEqQ61dR)aOas;OCvlCXkU&&nDI#+?P6)LS(E# zFz_jZgG_xX4psYET4|FZmA508El3}jxaXhEYF$jbDqM2U=`zc5wHaHaHms<8b3b2Q z6brvx8)rJGhf&VQ=UEGU{ge=1S!3on0V&XPcZBs93TtC=-F4rlUeSL)>SW+_ zJ7~DS=mzRwpQNir&d(b8e(+Ydbtrn z;&oNXLNjeh*J^}wS^AcpoeN$wJBU#AL89*kgcvT4TMWnMJ zp?1=(sk6vqFeN&zfCTO6cqh(NM*n0!M05uUQKGo+fM+OK*hZ$gbTbvcx{PGhEN?sU z{g3=+z4eccReQKrA_G+CR3x}&(1wEbWKvwxF6jkD0+A>nQHkty^PgKOa@9Wt+?c%|Ci(N0>S~}*vUT9I6Lw{ z#T-WQmHw}yCvn?ufozVf!P?g+@f|36%q}pY`uNoesJt7jF@?kW9uMO`eh)4RCkw$; zKTVqI&U;xA*yC^WIbh-Y1{fx?SsBJQX?!@3Z@f{)*8ep55P*DJ6WNv0;H2H*O->i` z+fiG#ob=;vecs*1UX{D<+g6cm5QJa$c?2v|fiNeAlo~ZgTwUk}6U`spw{2C>|3%ze zHpRWKUBdsyoyMKu5FmJP2pSr9cXxt2p>cP2C%9{X1Pj4~JHb5=B*8*pI(zRk_qk`z z%slU&FVNLhUDfNiu4PBBnfs?BaN>#~6cRJZ`{&Uv3bw{tqiPxNFG_V&j{@KSREU#P zd((wqt`d=*Y(1JAb3(t^()9=Mo5%TdSqFH3~n z(bC``6n{3|;$Kz!YVGgQG)y*WaQ~a8^Ixa}kK!)Vu$dHsf(WbA_-~W2e>9y))%?#1 z06&CO_LA!JKgm=2v0y|2auO1;nfjcMbQCUsCr@F~Yeu(nx}c9|&nZTz|J)i&1S!w} zYQ559 z)|;fq$_@P%>ePC}U`AbeO=^iD@?1w0U{(nl_~Z^cC-QDOnic;PkJ!8S0?c#2bd+>;k|(@Qw1R z;B8O$T~tIX^7-eoUk)o|{atuA5f3m*NDyr~VL1@KJu*?Q>+guzK=$U2-X`Dh_uWmw zE6+9e+`!8T>q3Y8=M|H}MxZGvcf=JK7!9J~q zKEm~A;o|aaVRAb99ribQVcPMN!%I8KtXLlDu?d>=>Z(~ipLWwiF{L&1Bp=lXjqJ-J z_cD!bb>|>L&%>7V?30eH3|>WtmdhrP*zV zhwsVJBIh^;isnP>}Tp)CUMRUg)6jOf4At)zU2W|CDJP^0aw(A|cm)+7|4*`qcAgiBd1s zYsBvgvlWg~f&v=CfkxT%H7p0&YdeCw&IMq7^7jCAu^&%+k_z7OZ$FwE34~=>=liUb z)3Rdh7CrF_gw+x$`uY?3ygi+4H0BdJ`?yj2a|bTutDi^TVqGKL_>NK18T_+1c@yMR z`7A$Co)?}l!BC}#^&~uS{C4+q*u)=anJBMb+xNFIYNnEp4?hw>2(NrG{!k|vnn4yLHGLshj<8m13{P0I!y+{>P;S%ya z{%+QlX%Ctloe?pj&jR;2aZI|jWa}NT_#ZD4n{0+DE;2udAC4Pg9?{Yq4daNP1t*5# zM?M^X9#M*~r@lciW8%E~5D9Tjwz5Eh%UGyO@~O5+98W`=Ltf6@>)2m6d${iW%Y^RQpa#z$VhEp^}E31}L*TTiBa|HFh`h8V~4 zTR-$rfl)9IF4psXa~`(OfzZzLFP<~5xikhNtRxjrh33OF_yA^w7);ZFihfGA_eYVK zub2u$f~G7xY_vS+PDSheD8%v@mhhTZ2^DR5i!+bg&SW>8j5hb2?6iVjlNk~jJ}0mm z` z{pAP)Eeeyo@up*G&Zw3q((1uT`kwotxmYBV)*~B7$(7bR6}s*AUQ9M;ZZ7@i;8u!G z0%A$;lY!Vft&XYRwGLz16FK{-DNDl}FWY~CS1wUH-(v!9zZVk^9tjH%UcNz!5Y%vl za^#)|46DAVDBgW5Pt`zx$}k0vvWf zt2Ys^ruqcCA!7dr+5?Y5&Oepc7b1hpO!vP7)G#NsJAn%1oG8^~(I5X$c3eIV8QYa# zf(u$|%pWK#c=@M;SuCV3*4CLpQ5G(6U0*IaWa>|GL4fQW1rYYqjUg4mqzWd64d5b> zB)^luQj$Lt?%$#n2Mj;KXb%y?bT#TUuEy$Ip%@^)1EW11&d@5u<$Phe<0uI z^luFH6m<&)c}~Gv6u!0!1795z4cyv&v^1e=wJxUMa+xAf?sItY%LM5WLGBRJG`+~tvqHKYg zRlI&?h}pxl(A(HNr&HitGq{Y_QPBB!x`WV?m5`d^L^#@MJ7#6cq`qO4{aJ^d#~4$` zH&OSx4kgZXZ6lkq5XY`lw36>1=6`gZ%EA>{?sd+5jbU%8q^mhsINJWSEcU%h-B}2E zv8tiJb=jN-s6^>5{qUO$zp;nF+}DM9c74btSa`*SYj|Glfo+6dD62sXb;DJDQs|wl zyyIx+cvB-nUM|`&T$}-SA|G<^)hy`2A%~lnJ&MO*MredMUf4 zE^@EOqJl9w)TPCRmDlm-x>*|sR#^}4>a({`j^v@PB@Pi@eOReKzxs0@@@=7gd{HbN z@g>(gnAkng~(PbP3r zpFaW*Z=hhhQF%7r4`deb_=RG|4+~!K+TK$HWaNlahkR(iw%7y7r^C^-hx-Zb23~Q* zQbWp%F)f#1)~CTDbZugQX!Jay?kH;dX-J)P7DJU+aBTf|$7i9|0Brve`|S8L3;r3A z33spARlFkN53BSzF{;h_(oJoxFI*dA%6`!ts~{)U*uJo}5;l*KNQ(SpI`A4qV35E; zGq{DB4#tPskOYQNNYx}mSHf5c|27@OI-pRa`#_EiLgT$#U!T+56z%nv zN413hWjZJw<{;5|8n4=&W$b<^6AKyvJD)k{ip9cMmUw@-pvGHqP`DH$^K^ttYB6C? zg;aag)U!IeoHYzvK1??Z-SdmTOb4p>_^P;SX>99=3WlVB@wIyJ2J?}e*XV5ekb8MC z!ZDrw%2{t;ee>orx-~JHn|T-&UIbnkvoqXxzl; zA2kGbRx*~5g|_!UYn|h&4MIW`ESb4eC-6@U7}d19%5mvCYL1QQXS6>`;MRxYv(O;x zH;0M-X#8Ox^_t~4aRiRGgfsv}W)V%&^T@rj&_hv8Al>G`|ntlY9VJ)Vm+r;yK`R?m$@tS);h%q+Egj^!QroeORQBFz-j zj83+Td%j~fP)KruMHf`5kQX9#zr0s;{4rGsev4u)bi(vgjt^KS2%qL?8p>Zk>lSM~ z@8qc2st@w!r{UE;{t({IVRSLTm@gmwsnv|IT_=u`%}@>w?w`V$|3ylHp&3j9?g~Lk zU^3A8-{{tGW8uHhtn}Z|3#=cOvdvj!^F-2GxGwKS1UI-Oh1aVmNa!3)kp`(rF+i_E(?U-7lZf z3rVm$AE7>*tL?tFnp3MfARpyJuWvo{oG^(Yk1i`&Z?y8Aw%Q6^l&TDq2ezK&nJtst zz3?u*n#CVTgGKvOQ+3iA)spxxn2ySssfnS&sKM^Ej@+R06&%1IQoSg*jagN*Soev) zDnW@l)vW5H4J^M+(8sLe$Xd*Z_oln73S8aIfKF=BvV2iO!Tfb`$;z48zE<+cqWXow zNAcCk_RV+=yw(aMdnd``iYqPcqqgcgyI0(T2ylllD+cw2bCX+MbIQyiv@!17^ z2fVJifmyOLBs=WIjOrWlP0WJGi9a$@h|&c>OSDnlwN{>_+NPT%hds@l>Y6!{{pu(W zNt@WHc68sFwS0q)O>}mVRe!kO%Ty=+wU^bd#B(ZxZt?4=@&^`t-ECa8L^hjJyO@uv3mA_-0fA;g*hG?ADHdWlSKjn96;nY_ZXFvm^FH2%Ht z8Kj*#Mer*m^0x)3_sMoAj3cxt&Pu6H7I+|}S46o}z zSTq(a`s>9Rug8`Eyi62nrt^O+bb}>g_mOBC!xDsW_PRoBk$sXNbE3a3bg~d6Xmanc z1p~>*aLf`Fx%Zqol??2Gcixy-F-0qmK-l2^GbROzXO5Odc1+HwDLH$Mjul5INjW$< zHHZ#{QZ;K-MGS$c27jpClSDpl?XYFw0*7&MiCg@dapqd-pqUeXQ%p3ZoY`?Wu?M|ox0oY-0N)l zDoxC49Z6r!6uX}_+3t4Qc#!G8(ClTdw3nPVl9pSoLmZ2oyWS#_R%t#TX0Z{n{8B&Z zbwlJ{GGEuoM9KC%dz9k{FRhRK5HDeFLfkhw29}Xgz3ZH8f7S?|YTQYuqY`t)7jm{} z>e=tFTiIG|O>Ftu8_uh)+h||d%TAB#msb(g!^s}DV`bM$E)%wQ%)gNJ8(TAYBuw9& zAskBeFxV~E>g;r6b1Sg#-71GSKc%Vl?G{>(1kQ7}G107TeIN!MH$7(_k(5!-A?lZ^ z3AbT-gGfn6@ikt_P0)Jij?jk0<@AT%!FtM{LXocD@X7F6%0m$=D#r6qK7uIE{m|Dw zi!*p9`0!W(8Y3pQ5c78{=S3pg5B(A2>22)4>Ut2=;-KP~w9Yx}=cHUHcsJVgT%Ov1 zo&V0eA4{KK?L!g=x;|y0PR2Q`HOj@a#?jeZj2uO;#^q#6*Ot$Q4QQN93AN$KIF>*uK~;Px~` z7{VVUoG^?u4#kMR-i++04&QRPc0N?lex}!2;I@*)RHE`p5uz&bH@W-P{x5Q8$hVWE zGH+up4Y(F+Bz)`*(=w70oTW|HK`O%*HDG(Ls%i7{Uo=m*{BAbg;8-0e(@y*^u18Rk z?Oi^|AbQ_%M4|fnC1J0cd-{l0eq`GmV?lt@T&XOhEH8a_lvb5>LEIyWy52w3&*NQL zsoq>g0bG$DI2W>$f^R+ z?TG-8ZSycU%pF_H!;;L1wQ`<;JZzY&6gpqe85EB%JfEQ!*1!8abQ7oW+i zHC<|mG7NBr$%H=X82J>XVGS~THb~^)Su~iKz$>5w>sbZYaEx<(&K;eS`a;KLl#3bK z1S@97<4Km>aE%dD)0X0yZe4DMQN(ix`UyUwmLFrvDa1eLKpKkE^OYK2WQ*vyw#cg{ z+9f=r78$ksQ*e1tr(VqMb3?AMoTobgTs^i zt9QObm*eW1WS4!!3J+0>50D>tb~_KEk|A4^x;Y^MY+xRPz4rUh|V?QMjE+nViemUQa?0>!Jw!ym#-EeIat5n8rn%%m2 zCvr_x{3QJQChwWgS^tu93&&=Ru|~gGFNcGLKjo$I>bY0uvxL&{mP4eOkqV>LYoZC;BTG7YIHOGvN~m)) zG0C>i!$HGCbPUr2K5&QH+22BjdwQM5t9a z>=H>2>2o&Ob@^37y0Y-PeR9M#-KbHVKU`p3ze&wCM`4xir3~NXi?fX0+-Qy{fpL{k zIK0e;alZ<8d;d4$LI_WXEQW6 zwL0*6vl#5jExsq*jgeQhm4Ol4JT_I5UY#(Lzd+ElK|&zhjHr4kf+M{#KA^^IfPa3J zQl4IJ!v2{MoMwfdRszgRVk#rQ@=n3M7+0iLSiO1$2%WAsh}E@`m0#_D%GPS_H958Q zh*??e*NWlFadeDe!C%{7pdQ*g6%P2d>bLTzN zH!Dr2{MXCuo9;tJc75gQ_0y_FdY;xJ$)udwYtM@w)~I^_bzLwq0<`Dakmjw=`;BZY z1SCNfOp^$CgLFt+BbLuOCk@MTgo;*o1im~RlUUFgN=9GVCq}2VF1`DQOzK3Oa1>>OJR)WVHy25nNrS z=E-qmva_0^#j==iz`DxW@>dU@TAuWvWMU?ai*nR!{^ErJ6sGt~e`x!m1xjBo+#-ic z(q>aFSn%-5oT}2&;AJ@o?J!~C#A;n_&v)}nSr^=cF|0Fd^|Q@{}t&$`&XulbCu+_+fS_b3(Pt=_$RM0T>=(y?atzOr}XDmo8y}dKl7)r zPI`2X0vaw9$OQxTKfdN!336FA8%ZoJRV0yqaXN9pavs(#>t(rEkFkZDs{axO?CMw7 zhT|PBeIG%GRsO!oY->4@@4l*k>u5e`Nkrsr`E#oU`2Gd#xv$3Z9aC!|-3I4>-D=HJ_i1lsNbJVsFT zdIFiXF)(M!TdCnA_}iWSN4|5+^G@1CimPSo%^=Vc12%BvC`RG=F$<~C5JVn99!z{0 z2K)OGxS29GaG)vL9t)1!@Wyw|iI2z%8(6fO68FZTaMQAmXhv|?)KmN;pjCWx({de zY`ti$OF0QwTTU4R{BbyX>r%jhd0V;-2~}!& zQ!!iQ;QICsX1V+@uU9JvUwA30!oOY-)2^QN6ncaFL~`?@{UIPm4604nzSgr`LJL$@ ztd}oY5~X@A2ADH-Y=&YhO>b3t-;nJP7}+8pBx;A;%%^Ho+OEMF=A&%}-e|2K78NLf z4=Tmjrgp24M}2|10m|MNO+o|j6C6cDyEw|Pz6w>q{K~6`F6It0TcAk8sY?+5Q}_1> zWH7~>*s-`KTfnBSM|{oisV99}hREzLZ#C)bRBg)H<1hB1z>jO&%}LVf?XMoGncniE z83V6(OF_rj9!TyuaOynb$R1eU_2>pjh{YmsMsaU&6y%8wip3CPQ9=M7YQ!t#E=((B zVy4s_4m4tk%+RfHT8m_{N0RnJ`q$H{&zfQ9hC1p6hSZo2D0>3oVetfu&dlX^9uyl~HB>cC5Jo1BK5S}lFSEpJp zezi@Dy9xr?C`u_6vH-+^_%bm91E9fNPJ=m9Wc@*O)QqyS5=sadiycFJydxuTdO73W zFv`}}X1VS^)$+fG&_CW*v`72Xk~PGZv05&Vz;a<^XrnLB#~Yv(-3Nqh6N`TK*`qBkR7R$c1C!1IN0 z8?u7?Sx#ORUB!B_jWPe^!elVbVw2N@MKg*6eyoXFs`O5u~7PJeo> z!*WNN8By2R&MqJa?CeLwi-w#C-R%H7uUzTz53u^LL*OtT)ptT4WWz<8^0O6`-pkN11Z+h+|c+N zdN3O!WfaUV=`seGUtAc4=d7DB^Y+APavJxuC}8@l4PDEL!O_L+yrGA}i9I?d^!zlZ zQa2g?!rYW36l+m4)mrxqF^bcqFoYStGfDCFXiCxAbeePFs7X1H((Ir5!Yzx|7^xWx z>W_b|b@Mdg9DkKlFJySSl9jv`*2p$iVnIv0H-L}TQpi%Xfo^>}b+gV9P3=RlaIMh# zHW%U+=djCVg)kK|=^li`YAofqQW0&$6JfO7oV6E68^R#|2Zwd;~ytfK?o-OGkCP81;Wbm==ccWRk| zTH^@on@u*dmma=2w(vRpC8f1(C-0N3V_vLH60T~nN8-3u3j!fJ2YibHojy)D z1?&@>Tl&wG24ugd0l*R8mv$xi|8_73!?Fh^e`OCq|HsVKCW6sFt8S9fbeS&yG~=Vz zsX!$-UcJwey^5U3VfiZyNedW>nH#0bv@ii!$;r&EBh9eZYBJCRg512NbT*FwxhyHn z%v29EGX=@PvXCL?-ymtssWb~&dhK$gwFi7?{(>^kA;0sHgTt|0bBNseH9E zzvs95$r;9W43iEht z&1qLkBYsORFcpikKJ*DmW&1FJ!uS-~GMc%LZ!ginSEJPJ9zPU21$&*49zcM(QN?ty zhG+uCJ)a*)s(BQC@xS==?n@phaRjV5iCGSH^K9rSr_gnw0()-~@E?@m5x5>?=6MVq zWa2t9Vk3JH+{b8SR1Q^ehe_BmOQnR9Fcqel>Fw)h5Im8Ro9caPU9*0-zcQ6+9)70< z)K;w|nn0fK9kGLS+H`Z@^LAO(`=JrmG@#?eWa@yH(j01Y1Wp_!rm#wn@^8P%I!a^{ zRxj)Hg+-sVpVR0%Ay>~>)OBLvtftYqP^d17WN?zz*X?=&>eScU@~52$IAiloRY7Ts zz4-9@b)p)dbRsEk?z6y+ZARYs?~I@8UG(mr$rA8y;*T~~Bi_MI{Varwal>(qv;1DhfjGp5@teArESxNcE| z(HCA&9BhyeK1Q=ao-dZv+mokip}w1b@pNUv=&42-`LvYQTd?xXXKFJsM(zgPTV(a`xr>aU%UBS2l(Raty zZgk^k-P${TjS86VS+&LJMqQ_DRZ7S`&&swRuJn@fvt1Ed>*6m?slFQ>Q@8_S%DUb%`&`*8TQaANUb)TN!Koc(?BsdEZM!`TJYFlRH`A zLzQaJ!t(dGEdrU3OxwbbclCk0C&r*tQ{;2%L=8j|6XspM#CvfS9$Z*5pP3kX*~tMD z5DK}OZyCTeQlb4Og{aEInfOXd&|@-{z$d}O?#5+M0B9*s+?g0kajC+tscI^NL=60b z9{7Ecq>6^C7!2WQ;&I4uf z!x`rpF-|P8lNpnC>7J9w2y)RSWjRbTytM7Zpizwq@TX&D#~l{K+Iv*cG9Y}DLDVSj-akFYf#8;gpgY9Hz%MO%=8|RMZgr@Hsu&$gO}_LXBR(gP z=9bmU3i{c)h+n}s#dj}wni7@T-XPKAt>#fx(-4-z8_ zgUP?Dx;i_>L_aBbc}GrrM z2JXh?S3(ll!bw%5weU-bYmpQ)?&AQCpJdt5RT?p_>2EA{{*r&&qvtc2gUh*kki@e| zp_%Cn`9wITVWr#@t#y0B?fCR6GD}j1m)zMYQr7$^#gl=!b97M}_5D_ z=V7jkzCvG_etMjzfp>Yx~SMR6~(Y?y_?0 z#sLVOlM_y!^iA+4-bBPK1dedzInZ^s#&%~+6ML4+6>_cys-N6WQVrGX_o779GkH!P zHzzpvEA1cFexG>_*oPp*wspgERs|E)n0$>s_Zbrz;`Em>-I!1CJY8bvz}wzHjh>9<*U$06hIq-qn%d5sH3x)R;%|7`B6E+M4%oRJDZZ3ud)>1v8Grafk{bs4ir zljclE^)w#uwk8dZ=;1H%;k9c6<&<4olC6>07tLSge|*?~h5TYF1gW_gGl1)reAX9} zM^|Fyl^Hqhdm5?<9*B&BVG14eOIZ33Nwzq!+OyIb1I?zY$`zby*PrwCABNSf6=yZ; zeW{oEhi*M5PK6!{6&&r5yFlbN0NsAh zH_M2n)jP*)xdM?H8|AK*!$}vQZXIyqCi}P^-rlG$=alqTYvpLNos}PeCq9HuufPL{ zOn~z)sBjALU9LuQQmi$jKYMCh%b;O27}EwyMtl%ntNYuzxr20p>U)(qYyL&7m%quI zCr?+d>ps`?0&*i%Vtz!853U&>*Yr6v?#3N^&n?#0bOjdg#ByU-3h)L88I8`QC4{#N zPy9E5-q2~5;2))o8MF%Zb+ZL^`jyIgG@9-AGgn<3wb;V@@99I*aFS1qyMCWiakh%@ z8iC*A(an<;9G8rXCbGW^ICXo~{-K&88K$^>-FWTafhY0ZS3iT(#fd!6dMr`-RURDj zlTaTC`)%J<$N5FL)1kQVeW%ds1sqMx4wAJ<3`Q~eUSjk(s8E2cA`c_yp!)zdaDC?4 z`VBm%@Q!lAJ?4Sb<&ljD#0dMBD@1a$1sQt!rr=k70m9v=HYCjFb5}SA?3GK5umyNB z{$AZN@-tPwUxFEwzqMmgf7tne!g%?6zvRGY@15x7OrTj!O3(WsbCF^^;37gtV-V*j zvLA>8tg!CZb$gnP~Yr2AvHSgAGUW09XYJlfA)~9$Fupg@Bg|eMLZAj#89btF6*UILYXD^vtqtldaF;rjTQEe zhR?G~m1$#zy$oln@}gk_gPD)%wyjqL-^7B#I9|t%Zb4RHDJs-QSc+UyUtQB7BN(@EtZHtBZ^k9(_?$$?)_4>xagozAIr z1EnUfUG;VcZ{U_547-2l8iT(3)%*A zd$HW_muab-ClkX9DbRSCise0*g0f{cJ43*tc#Y)%5eM^Tg2?q@Ti+|PZ-2cV#dd;e zk+N{K$9U%P6H`>LX^7yMZxft=O%$j<&m+@r8V%;$bQ0|avU!Sua28n{nFB{zG-%0` zKHb60Vpg#mANN3pHJ+XtFm|FUaWY4;DR;HaU)(Pwpr4=4MJ%!fi$)V_ypuTQ)Gg0{ zT%sn;0_jlh46WO+Nl<2ZT7o+}IT$SrOSS*(mdg)xK z8}-p&n%r|%P<^}goHW(3Z9QACFn&F{n%QzN4N_nqpo>K1c0srXqCg>neR#PVq1cCO z(Lqu@yP{w6zyNiGMPC7pLre)eb~Uy=SY~Z%u!(@M*NPZ9mi#lvD$UgZ^{V_?!)@dP zxD)@GHF3ZRE{0nl*D4Ly0L5BY#;~CLIJ-%*j%TRV4Y>Vcs(=tyK}11JLNJT{%;HiU z@2QN_GsGv{V_f=~$Tvg9<-V3ibVb(lRO>7jofdnyCj)nJr;`$Te)`ec@8VD-D&=g; zG;dR5K*3weHpFne~;wk2PhfMw6$7^_|^yM(!YST!kH z`7okcYcoDgOZSCwX_D58MtT>U#TxpT$MYHL7^g&Eq80HMhFBjDHpYf_nB8n&p3I61 z9fiW0uLc$0hdLXGmnJ56fkyPZYsdE(jeXii3B!&(1s1%;7nT3j%NNx#kpXEs7ZFD3K?* zbUTdWn>?ug>RAYn3I&4$GTJ~$10|uOHUNG?ExwCYjzv=!*OYBUfkR<7W0z6R@O28K6#`(s*(j%Fb(KAYUks;1 zpX4NQmGc5ML>N;oT`N8%m(5{Ma4hv{l3hto_td?FZ;J%iC;8x+DFk1`S3pT6dN8{t z*d`1A{L`zMne;RALM&7?+z`rCVNf9yg4e4ulzK&7OTJ&q>@yj8Ih~Nsit-xqUMXHs zD*vim8#WN277|K}VPR7i)#5r64w+M6UEdK+B2{5PGcV-TjKmziQqLtlEI~t+;UBjt zrU7x&$^3@sFea;loOr4*V28Yh`-G5|Rw}(Xd;VlJpl(=}N@8GGr?wL6QP)&+FORJE ztXQjx(*2!i+KIu@Xewk|z20h09HW;bLI7%l4?81aF$+ZyLkqJa5LmHvXDO;};K?c! zYwfhh^yZKXTN~nP9js$89iMFAVfQ^GAUuR;e_&?Jzs4kCL zdE!%1g|n6aTHXm?sMMy@)~&mYbMU_D+Qh8){%D{2#vdLddb8HaV|5h(_{c3bcZkBQ z4Z_H|#7{12R$s6bTvZUyjEF>3lZ?<vl97=YiU#o4RqaIA*JxRI=qt04_M(N^%>K-C4dv8RC?IpYs7#ryY}A z0STZhB;VeV?f4{e=KE!ElJ}4u=ud(ofOB|eP@u1LWJ}mQZp*?-^8o=X-bdB}rq5r%xqW@y`ay9L{5QfPnBB%3*E8i#KLs|K=>4L|L z@{b~|0u8n#;o~hH6!prjW@}I>{NctFe82k2Xu{f` zmnz`0-6<2smAzhobo}oa1L*fHP`z2u5B;e!oc$T>F4CZ>*Y>SLLG6SN%`$#yoIx~} zU;v8B>kP%r2)b?$qO`&Ia2?!17@X`0rh|YOAV^H!P-fyFw!;SVs1A_6oal3x!mKG7NHof zE53FOE@Fz_<3Ir##NRDhcveIgT!xSnhj#OZ1`mVlmc-DgW60eh1gbH`5K@kon98NV ze7M+;46za@!8V!UNFdRA9q?#{X+J*hqz)GB0o@ZC?V%IQavQ_GWVsY+J6Pep)UHSQ z!$F78v8e&Q($kOwQQbckED+(*<{h&opI1_bb5`TF_qsStmjU-~-C4#r2hIKHvE9^M8lAig*k256?BH4MO1ThKTftdxw zTIm#OuM^_&6KOyxI*cj(QYi(5NEpkB0+lJ@OUcWF3Syl}v>@QwUD6?cJY?A)*%bc2 z7r6Y_bNVCd!%%f$-`|_*|EueGjww+a@TC$DWB70Uc#N1pC*lj-)=Z2SlS+ca&>D;D-% zz_{7If!2)r`c%E>pb0`@UFOz>5hofzoPrINw7nQ+1E}191A$w>BS%Ub@u>qs66}#Ca7c=;_M>T{5m+I6CadgZQ8VsSz^(aXziNOX6 zg3mKN9T=XMnN#DlylZ()rdm;GMZhe}aI9X|fdAZv6|iDHQIJiGCdkcblB;%-oZBW< zL#E(g2olw@$}AH7fz<0LHIZEnjdEV*uA@kEQAth^&F?(xM;AZ>y1}3IQF?AS&GUWk zwER`$FP%Ba3_i{wehokof+rea8hd9mc&=7c8)czZhHh5L-JXLE zH&AVlO>JyL@2%LK*`Qo=&iob$GnP3XD~*lM%Z{19gx!H0GAF(di2;@}2Y4@gnhOGa zy0iLf-_`hhL!nUe6Mxe$%_&)rM1@`B*SA+<2^@M$Ip-Qub{Be1sowf~5>I%0ItAm2 z8obW=s^|YGtb6Hbo)jZ;zRIqUn~M}?d~s@&5cWd!Feht!sK4@=A({$(C5AH;FSp62 z{;h1Za+iZP&m+B~i=n)+1pY3q5Z(A|h@VR20+P6G(L1({*^Tw{`5@2IovkAu5|B z#c(MDS1r%{!-h*>!G$_en3mpc0A11u*UW9(0#>atsv7M|Q@*>K@V-S>hk6{V&)xDR zCF*P4$tDg&S(K?=Iz}pHgrq!$PmDg56Q(QhSwr78U#2{dwM3#y|3Z#o0W?f#q=sfk z_oMK7RVu11q@=VHmvcAxJc*?U&}CLK9SG!PDYeuz=Y0=-_mUQOoa+uLD^hrqPnHA_ zU_&VECuVwv&YWfk_k%O3Z-H8o1j>46lM?lVDrzYT9K(fBLYihK$RCX#QkYtbW+^M# ztWlHGf2@Q($Rud1ho3Vun+jx3O2Fzz^VOJ>=znWThsvoGJJDh21jt_DHevjLb*Fag z9!q-Ozeq;v)p^RcG_`9sa7eu zBs=B}>u>250xFx0sQmGU%~2X<$M{vMd2^~ydJ7J1DGekqYZUNuz%^C`Rw$+p=6JaA z9Em{~N%WiiMQCN!Pmw}a6Dd~P0Wj7Or8f1GNv-SW7%-O!O`Gzajk}}o>VYe6L%{ksKLS99>Yg{b z?}ek+Q{%?@TO#Tm`Zs`qpOG8=Zi!LRKJ_>#Se5^_5A4Yy1&o4v1rz(NRK-*pyHwL) zkA5nwKLYJGSY4WoNvSbfy9RS~NvyLf&IOvL|8(}Pe#q~#$}Bs%pyTD4etK?i?Xg~E z7CI0_{HMstk-Qe;Od5*M%Nk>0^YB|D{x&5D+zhL7-&uBXwbC$?#6QpJ54@}<)abf& zgQN?a=0fq3PVcLBiH9KV?-wV|JgZmfK1X_Wk14)!z0zGkm+fuDOLPcLH3y#!A9~Ol z9vib+tSl>aw6(9FhCzRAE%2N7Fk-QKcm3KXmWk>FC^-cUP!hhX3W>kH+kiY_ltB9cCSsGbT19r zLS#3&N2e11S%tib_{IA*9#;@%IMgrNqh^Qvv(j~=Wa&3kz5_`!pVz1TzBIfIAmY;Q zALSt+1aFypbPQFGDoK%(1E7z)sfeuY*TpH*9e*4}$O(dXRwn=v6JU74MoSIh5(?c? zUHafwebq{wAE&VN^heiYdzE4b-ahVm$VsM<&kxvOms@+bH7Kf1hs z44o3vh=fWSgv8J#EdtUY(j5cCzzhssGjx}NbQ++<5F#K_ih|N2Vj-Y7=hpA{?0uft z`#F29=RBwOFD(85bgkEYUGM9YM2n)`Bwy!X+f3p@peU_zRtgB3I@E6~j^sLQ*9LYI zbN!Aej>9=ZA%mfqfE|M-r*S}+bdtqcl03qa>lSbiXp)=PUGKwE=+C6MbB2a*d1CT_ zCZ(hY-RB;KB}R!x{2IP9fq@Tk+F#`eQdbQ6;)Zp}VjexTriB0mN6NHrpNaLb*97Yq zx~W{D%%`xa(H_jNJn*E0)Uq&#$vS*haN5?E?;Od07t8z!77g^O$RM=`8*+ zjO7^&0~z!!u?2Og<~+P1K*>G|k@W*6s44Fc(VX7SRP@MXFGn+~XE8WsF^-~lIdKw{ zkt!D=``Hkmeps`4X43efdB}^Ikp0Zl;Q*I%7Geu7UJuu-hnp^>f5-}#p+fR}j$Sw6 zxEKy}`vEE$*=55tsy*2e?euE2aT;7XBD8rD%Fa@wS$bcxw)=C=uI6NmF#=Om46?b` ziP?1O(5QZhN8X%)gekeB`APLe1C;7IAN4JpfmHxIc3&DVP3(vL{K zKf@SYN10=2wHXCN0>547P$y*5@Zxd^DT@S{T)-1HVzv!&JB&ySXFm5WAGS)Ynllj> zESOh>=~fdcMpNG%+TPs`s8A<15q+B%(I|23dMzUab{Q!Tk)ZMj?BCw8^$hVscL5FF&FS)(F8{XKi4yX72bY`9+e&fs-ngA(uBg@{Rfem zK_!;y_&S0+bP$&QoMf~`EN5ydH=8X#eO#VZQ~a%p87M0~J}Pqyt`JJfsIAqj|2IGT zQ^FYb8_U!kU@T1koiUoa>6HQCn?@p)6%6>7F&h1F*;`+j#m$73{6ug3`Rre7T(TEW zN3GK)`mj(b_RlkC+s5S@?(B`Y3$-u)6iK6D7sX}5_VK5+{(zj|;S4eNe`egN{Z z201Gzp=J98*GnjghbX@QJ%_|Bzq(DJ+r%0qv8T9xjH>Y4iT{fAwjS%`E`_hZ)(sC5NsOpZTV@@IVwIYN373xIE)w|^E7~hv?MWN>^TUf@-`P(J=v4A4 zY>2Pxc@+=Q$AmA&-9*y#K80W5sILY%T>j<;oLyjUp!PR6K)Gd@&v_y&EZ+;KDqHDbFeg?UEePV_TVC zw}8-^l&aRQ0+-kZuX}2H*EUX>Vr2E%kR3ul ztLrJ3ccuc-X=8V}UHIO%IWSsi1)~LmLqz@ar;sTr)9&Arz%7S^UGF554Pww*razO9 zytO$0SssACYr;?P)bsJvk*v>Crqg)0^5$joh(F$vCf8iS2mIb+>}$@+@CH7R?d58F z_C3Va!GTX>#0JB=YqvX<#(v^819~Q8=<6iUeXQ~M%hPUKAAiw@lk2-K&Zk{TOgLCK+%eG=tMt+|eXY`lXdaa;K3%9Vg3C>djCj}o<%tOYm5fBx2Q}3h_2Hni zseudC&by0?~ox-yEM^+75ev=0i@J+A)SBV)m8Bx$WK@*!$e( zdx>Y)37l~*TUV2XE5&t)W!Fk(gd@z?MYgBLa;x4ENNWsdPM!+sc$x9_`q0QUvXH#) zHLDC5Ec0{a(Z%t81z%^`kfx%TOcr1v>h2I+%`(f&9-8Gbgu98?;<%lvD1g>?T5@ej z@&x9nz7PVhRT@<`N-k#PJb(Y$%(yGjWizOWhp)4g)LYR>hZiU3hRMd zHO&H($c4D_Gm&h%&yS4aNNp8q7vltAX27iW1H->F^Up2|pkQM>#=OQZPnG;fGO zHG{H;WCCJ3|H%cZAG<6{9$x0ze&22kU)n5;N;0S{XfJ|vb6QlzwuKNr^{g|SpG=AYdvk8JE~lkx2EkyhDYQN%GDk%yhaAl= zgnyWCNm(YHN<1jfF_hM{{7@E~0I?B@&{h0EnO7v<(I&3xr5B*u@H8a5z0wR&)1k9$ zDY49CW!qE3+S$`kqbRlvQC?ZS#eEk-t4Rrakv6S%yN|HFY1H+GeIMpOiOM(2-jMb# z6wUZj5Gt?=qvRr$y;+OM#!lbB+IL)d+wJx8k?6o3_z90LU^NS6(rZRhIyxpLoZ+Px zeVP{1%iSkw95tO{6Iyaq{*Fq;CO%c4i3Xl)^Z=Mdwpf+<(;<|x~^Bu=ACf35nB5hRPcNvP43(TDSR3TxC}(ejx+Na=VwBkh99tj4xp-&3fV zLNftpzi~!J>6wsopvG&4%|Pvy*^Py34WIDt=&|qoR%Z?Eg4MmbdkU(b-%Hf_Q}$q~ zn(t@oY)*-b`~F||K-z~DBso$A2i@AfQA!1G+lN-iZMU>(|O_dS(q^7up| z_UG}ueX`Y?Vy5#CQ+$X~*@8e>2#fLZZR1jA3o#y=h7oFqDZ4Y-^^9cl{V+V{AAzqzRFz3mE@*RMfESk+!oGjgml@x+4Xt+U}N>%k4g8c zJvRp|BeU$+3jS#L%wgZ!OF@0>R#hND=E1J}{lhrfN1xM^e(gYb^jdCJfq!9<8)$OK zwa_1v9tmMCwnygR2#B7WEOcr&!C(yMEcQ= zvu7HZ=QUYN5Si|uq$1OtB886~WwGB%`2nb`+T>dfn&pvbQ6Oexp9$f}G|UbRvm%_y$+5M<=#LBg&zoDhOS!K5F@R0%_D{(U`Qkol~fmR8$37)cB zceuhL)~6C43Bl1BL1yCDEIcs!-3hb;jCGq*BXaSkhnSb<=qm|vF4l?Y42%a1qd&(w z))f^2R=rGPVw5~bI6_mifjs{pE^$Vz5-iYz*QSp98M)J0(lqu!%;&KJ?qQw}!NVuL z8`ngQc$>jE22Tc0ud1w*%Q=A>LUKcQa(NwN(_wOxNAm9xfZZg89k}p(pFvlhx%n_T z&N|SC6L4{77_`O@hv7-Oct{3*VgWyCjUOMuw|PJqfD1ZiFhe-yYGPgF?x?GBNHQ(_!p`yMd%{?s^5JOd%2AUXZ3*~A&unf^=yUA|p2ZydY=8-g=9kFT$L25`_&o2lWgN~8dY{Wlo5yeC zf0PGUBO&g@JTFgqA6zDdI+~B(8q5!Q8cJ{<3776kG|0?nlJEuD zW?3IfUlVr|m-j|jF|nRN*dz{xdZZGw^&rG85no+xqHcH)ePU)j7qrUiaxrZIj#?6a_%Cbj7PaP#N>xzMI>U;$fCD;4^HF=caH>-ku9E8E}j_$Bn~L( zhiP7q7W4K4FOMkX$O2IC?^PnaWD8dqO0d0psI6hmIJXk>MS|fiSBXqN@RnHoiVIjC zr8x;LeW_fsfh(bENZRSieGnAyk`Tk>#5jkdhjW)RC(}!<#mFEN& zVW5OVrHtCPq9VMkaP-PvcuaB*f=Q*ES<=;tqJ*=de6gmO{x9d``e`^N8HC0Fn!x-^ zEfoxOhz}fLdy0s_!#E=q82PX37PTQ9ig1R`d|*W%5MW$iVQJeYc5D;7aD{iAstVTN zjWqi07=+T z2rR5N?YJ&u%uy^ab0N=Jw$1`AV0~#Z`*bGmiI-39vB3!77Z8lNcWmA?25(Nrws_q* ztAoxDzgyDj7&=#XEg5mPK(_|`9MHk~oUSod&(54K6O^81!5z|Pb5d_3`*dR>RnzjI z?+$x_lw1?mx+x&I>4JEEcfnl_D|6lv^L=i_7fIc3w)YPj{3e#nrKYQ=3b40#?pJa& zzu3{-;QqHdUVo-=_6rBl5B`l|w|?~m$QBNapx~%~9d`TTJhmp{x2Eg2V)W<__MVqY zEz|PRHPskKC@21H)jRT2HfgpW%@W0{ue@LYnk7ShT|NMT!vyjYoNht#8;*B|TE;>QeAU?lkd_?b3z~|9@@mC0? zpFQ(ix2tugA|BBW@!y$yR$FHLeewHqbe0H~IcPK3t-u{uJ)&*_>?f|o3&?L>_gP+C z=e8g-u31KI|G}Q=#~**Ncg6{;R8zGaGknyB2eDVR>}o#&VsB*etI&-};eTMyRnNP8 zXgoav9G*ea{>5J7zhIB|5B9G8EA}Kzb20nz=H8+e81`Z=9C8E1Uf>_>_5TBVT6Zxn zG)9=IY#U@OH1}QE8-J%Q7Z2a&xC)2Xxvk1NjVeADt&gE|hDx8wS+z(A3VHelz|b2< zd|SNzuI^Kd0#{l6($Rvy7F(9jb&=5q^Lolv%0{(L6)HZCie#@Ez6y-WjtPbOcKY3+ zJo-wjcgNX28o8%0en9SRX~M6()HuG`3G^>Eo)^oM%n9(&_VjJ>{)l-i@805VPQy0= z=2ngo+tpX#^9==YWJ#dX;b7l;#ALhpFZS$x!iPTR7CmL?GT<5f_UMPh&^PBQKAOJm z@8ho9)Jm=ABZvn3CO{SMT+F-T*?@7`@yK)CvhzN7EVj4Toq~#ONRY>abg5^OwEKE5 zJPpdZA@%Uvn5y%vk@4VSgbF#p0rfHX{x;EOwftC=4Cn8wz=aSWYbW zd~kiiAu_a3iUr6pbfa;SCf^?4fbgEn2w{D%d3a4xtcH+ud4wap=bFC4-eW$GM@Jh8 zwaWu9G!a*NUpdr^;V?S8A;zS;rzTcI`G4F#*lqieW=s>aaYf}F_SF1O_h1^Or8`4~ zk-z*$3;BSr?MX)dZXS!Pm$ZsJ8$FzqQikJ}m(kWG>7m;lmyRf2#>8ku&d^VAGv5P9 z=!^2xK3lQ0UNn&rL{hamUc7_t zl=pphC%#^&;NC&Vz{Vj`kgqEL7^cW-yNXUQds=Klw#Nvo$~L$N=o`_$5>n@M&`A_+ z(Pv~4z5A{Fc2aQ)-7CF?Tr%${lQ88BmZ_}*P@XpJ?oD>+Zf|AWFbQJ)OTdw!3#rbG z^|$zB{t_@9b%EhvY+>*`U9ICd(EoOLu5RipcLd29QI>0kZ?Bn+oXe(Tgxn?!yTC5G)*JPB%n+U$ zPy^0G^uEJwuCcA|z(LRRm@nBvK!;e?q=oSueu7C*%i|)nbt*`~LJGmSeN93oqecC> zF>ws5_=%Vt70_OLrh`V$@K`H8;Q||sjihn2A-8gpm6r%X8H+@)7tQF^a-Y;2Q~IT3 zs@$s8-sSA!46tyz7gTR>JK6k%>N-aEdZ|Un&h_ieGm3Ga3Z2**u2RYxwARcPJu~=V zR%FY5^`&{uR-w1vj!MlLzPUojpiB$unfb&Vw&ntZB**A?vw(}JVET#Mb;eiB!%RCZ z_mn?gHBX*F6kAMElVQW#bLl%1mbLqSEv# z-n|AjIK-hwoh6-ml-IGz;LCaXTe>Vv*o;+q&*(D?d$H0**IPGsgTkd6rk1iF_KkTN zulCMA`W=#c?slDD&-gN!mp!Hh?p!12JA@IsIwz$YJt%>jOUdkyM5;epe2`+Gi8bf! zmoD*3iaZy$|3jUMR)>?MmI$PK^vg#-v;NRf{iRj7_hZL?WMt$Gl(SMFOZx!&+JjXf zYC&)nMuQtI<9lt?HFQ%bjim<7|s>Wqw|TCR*ws!?P_wZ3{%osQv-S>-M1I-`r-XPwak zv4`V=Oc#hqUOIZm_jBEo7n=~$uO!cLmz|8IxSBk99h)(ILH;GCHMo2mm-F&PsqdI_ zjp3h;7w^(&XJ^Xz&c}oBiPO+_g1ezNebm}(e&tUN2k%^HPE}nE%H76$tj#V86tuGC z$(hMXA)m#Yjl4Zg$|oZ{5U0XPm@6$skCh7-2ZQcMMt_XotnH24wRrOF#KYkB#GT;7 zpKn!}0)ftnWx1pyc^a~qKfs*kcINB1RsPh&l=a9vO);!h5|^dYJQuxe=y?Z!LDa@Z z)iTcCFA&Jh9Uto8{#tmo>Ym&6oyl;A{ltD1Wlfm~isaXD<5Mi`%`nWuh*3z3q6@2s zj;itHo#|5f&@-;NL$c+Dq28SDIm4d!y-A-&+_-!EiH?kXKJqMs%KkFMhF@11>f{kO z`|!n0n#e`|tdNeIyzjWK?!*@to8>}RK2JUR`9|k?XwD(uejUx&iq<5YN4RVYXRJm6 z6-*tDJ^d{>{n7%h*^#No?;ri4u-VIR;mEmV&I+-IUw)Q&&(=B!Y)y51tCcxP#Bwvt zlYU?9@6Xt!0T@JO2gqs$0IpoDjCZ{ZcyB6`Z5Q)PaQA{}9R_KTD>|FCnIn?-F^DPX zCz(t$4WETVsdR5c%A((JKPJ6xbAtV>Mywq(Oj-yq{=TdFx_-ZpLxRg(*z=0dS^P(0&=bGb?<|oY0i{ zc&Ds5)Heg3a-FT51ch!Er8=}YCvY_^W@bw2W@n7_kA$6BFXcM)8SzN836s@=6onkj zegreMhH>NsoWvR1=cPyk@o}|@mpFoiwh~)ul3c`-Y{Pc zhSra(m8=*)1IM9d6Gzk&wLK6gG^m0@1fT!y65ZSEoXKF9>yP^UlI#9ruMWn#w4V&p z?i3=WMJa{BFNHlLg?;}#NWK+6UJvo)5OMf|9|I{APa@#Quy}p-=u@kBCV%fP62RUM zTn!X11fX(L*kmO<#N?0k-Ywu?{J^hsrgkf&c5_n7HPa^Ur#U$W#crm)^}xRiOP@Go znOcDVB*A;!AiE1xREKGaYN)1K>z%!6sXn6Do2Tq12PJ5s=BWonx$=wOp)@voI;ojhI{KM8GZ*t7{2e!-Tp-zI0;dFH^T{&zx2r zXHMmOA~I`XfLIbvD8n&U)D!(o3w*J`_dIhNkWhxvJgXk|c34Uk*7qt`a)<=Hnv^_w zRKzgw7kl*vkbXe(fI|2$_Fj_GRu-w8LG1CCC7+N~yJ)ezv}q*k*uA5Y@AGibg0skC z2HDcZo?^&UaTJP{0ZvJ#Es>Kg;YHy$!^O7iOTHcIfTt`^6aHdPrJOaHo?+Ff%cGQ? zoAL-56xCe%vp!`3UM82}37Ik)2`f8CD1*x5_jC-4Ez9LqDk)cuXj>S*fj-O2F%vRlw-Gl?B){S!q@TE+qtcVJpu5h;LyI)?y2e@%hb{s6W(0RCfYtW*Ji-~JH z_Y5NtOLW!dy>~CmHLW$&PYhL`3cq)=AYc??C0AYli96x59^$KBZLZ3VqePEKz08L@ z_XZo>;9U7NT!1Ef^P3CJfJrlr6oU3HGHS>^cfEPFftk;)nWfM1*AAKk3BS@U|I@a4 z=HCeb!Fg0i)EyYh7u)~dGMuvp=6|6H6aO6(GW`F?gyvuX`2Q*s?*30RVbM;;|Hy=R z$smcOj?yr(j@R-NUrOlDOsegz6A2?W>Prn?>PdTN+2YK+j_v2yE ziu=b>4u?a(o>=WrROJc#r2#VH6BFPncK?BNi+K^3ZHTNf!rey7mUFVg-{i*uJ=6C4 z8xgseAH5}p`u_fFLWcj=ghc+6HA+4}ZR1=<3nib!Jilt$vyk>_7Ntvd9POqu+HXc@ zp2wWeiBUI+VF_XlatR(F;m3``ZLu`lxsUo8F_wqoPP1eWF;*+VQ6{`37b&YvUbS5- zUXE&#!7xklmxzJoma5&U^BlPy#AYe7@}F3+3c=^51xa=;P7Gpu=;!Im`?`EneC|&f zGHu(Ddx#-k=aK_dPt7YyfX0*aLpdVZi`8f#4|3&1;(lyg+tBW8IaBczLa)-y=G-%!onQQL?aL0!|yq?`}~8WHl76zwmm0u2`b zG-2C6OgKBLIyaNIn28hk#EG(OK)iPR+ z(1jL(xqI47jg`+H-AHo+bTMlE;p7y%{jcm4+wNLVxQv8@cjfD+;8Tg724OXU#k;Td zF5Q)zumA)sAMCqb?i+2sx_urX|8iG@=po{FSdi{xV&2+rG}-d)+>|Y%(r1=fy)9>} zz}o_~!HrA2Gm>XkUb{;kbIp`j%$}CMQO`;1JYykiAs}BZVIqz+t$BArf(QXjr6br& zh0N+SmL*Lo{pfR4&eZ9GJfxekaO%I%V788vWtg$}EG~7|?lR6ewt+eO(YBH_wYzPm z-rb8-q)_`Scqt(*muqBoKZ-0(%n;YF$F>~Pz&#K9)Q+gDQb^WYm66d0SYpD3PN+sbn&B+-C3S5r%H9gDN5RR)()5seG z!%KTiRu*+HH={$pPgk%XG!NevxrVlK_=F}DgVJk>h!t+rRZn2Ck@qytuB3sLw+U~qY&^wdA^O- z0kp-XcR=wmFmbOFFCA(FBDc zrKtU`XxiaRa(qb7*lquD_zRox5$n$T6p2#m{N~IgO3JSp&%B+_mn!p8*nBSF`ej#3 z_w@1aZ#!zbeO9oyTt%|YYNs}2X`mO_phYEUYEA*Wc)F+Dbw>G`DNdUGWCr^i&<{5wtUK*A;;>io@(_h*^ZNU!k7V2kU0C&3pY z>FwS&Puj1qUi@x%$Jam2{q>-@1J~538eHL3?^aQj_~?5xC*5=lq1(Yy7WEFnX*^XE zzZN6r!E36NDwSR5I}LB_e6QEaM6XkFX^BIP51;V--pA%+&R&v&2UPZQFJK?6ow@m8 zEalgQ?vO}zX5a@PthPrfF(U9l{%EG~bPZKY&GeAN*N0YNGssw_7t}&wgRic9PImvL z#(Rg6RQTvy-l^a1?Ab?}JcCf$EtM^n43xU=8Og`#zt>X3bzU0h5E}0wKi)A88`}Im zTc-dce@c~zUZH>dg;Kfm_!b}Pdms6wBM_qGV*+k#UWK^-{x!#9k``d%_-)E6CacRH zEoX>=B3NFUJV}W5bv39=FHZ1RG;IdD1lK>jB4=;3$g3_r$8~{6$GU{P&D1Fvf^i3 zHwC`{P>d5gv7>^FZ~Wt(1R~V2LZ))M=vhQ`m63g20=H?D;a0+^J7tL#6DUSkDC(M6 z;%gdx6qCY<0LeHJik>k^M*Ag=lqcGFz_|&&oD0d#9&w)(QqTy* zW*OsRMoMpY%7cZJ9!}s9C;o{NzUL6ZkH8OuCM4iLBuar1VzqVh$q&9L>l8B#(?S`; zQg`a>h155PsVkrfw^FBR(x!jFH#xm|g^~ey>a-F}K@C#gom`QS`aUfEkdXe~I_+&( z8dGLkv!!}lCP1qIJHrlja2LS4rXMe4F!iKAc29epl=iqb&09T#RV`MTV9!m=c=`j^ zK@HI6IdU&%M#HiMm6InFvsl%x@#C`mK{3i^pRdpQT8EV*x8rv5aVj{UVqNc4f3BaP z0Fl{XIOrY1^=(V3#X9c(Le6jPl=f~;4P=hyVz6$H+h{PC7;Uy3D+VlZT88IR_~+>2 z&`ufX(XJc^i3^;>Oecvv%k6NRMQ7#iOxS4NZO?OekXimjhO0C|XE@V&wlgDpE=Lm` zDb!;X7M%I>Jw6k_mUHMFjDsSKxBv$TJ;bZDIZ>lo$)o&WFz8+%8={7ylKncfoKRoTRO-xIDfq+I~JPgp+hIEJLxd>#{)#s^; z=bDETDE(6g!;1UEil5d2>{G?;`xG()aCR~rU@)OM>jpWS2iw8rR6L#TieOSPw_gTnW^i3iSMFtodKfaV zqVDM!u=pokT8RCp68HUC`-3T`ol|ImB2bC4soDO?;Aq-_XQkqCR$Xg#;~IQ8A$ksj za8{`qMHqQB)cDxuQIe+^1-;gaQww&y|ytEmumibJ7%rgfLPlOXvu zqxFP|E*HpD0!YM)rC5jwc1KNr4^^A*74dX2d$;y((*ZovRG@J9PhK2TpEiY~-*&%saXMFqJTEt`2Kn#?@7!Z|6Ya&zDy3hWtLnU`frv;NuMj8 z{4ew(>fiGs<9~V)_*)qLzbivL{cmT8XEpz4Wr+Xj#sAWaS2X`*i2w7v==}dRFM@62 z{}WzB^56dtdyz`d;*CT`nB^@(J)m|kZ1q`0NVZe#j63lA=sAiaM~Lbr7$@fZjT0qY z!8p;`&{n%$Oan<{Xos85@d~P>L==AY)4hvF1(w!ti6OIl%_93}tDS{)^~?vRl54)! z$V_`)!U$e36%{!Tn0RSF*RZ%I#8&To-3#z-F>~i-!||Q5Qm>K36X#g(-dn2&e?9FQ zcm1B2pqJ_OtQkc+QP*c@>OJ&B5 zC9(=Ub!&;l?A{RTL+IHa2u3lgxpB%b`H{1(w@E`jmT8X{EHhoGx$7#eJ^R@fyALX| z;-hYKfqa|xwXTJCe-w%6g@!shkw8U$VQz|VtHrZPsh6{IX_vS(2ur2~I_XaV238gw zY`UEnEN`qhytH48p1S%(AVarht?!BWw(ZHH!>hZkX82V9a5$S(rA*^lKiSf+XULx`zJcl|AO~f&)D%x|B~;#OmV*!o(nvJ`I|F1(*A6_M+u(N zF@av>r#Q{vctPFCG4Aw)6B7eLlEL>f4gDZ@^_?0Ql{t-FK}Bjll2K>t^mKx^{d>Nt zw9a!ssOpwd{TWsp63^@AxyKq^kmo5?k6{7C7_c9zMmXgm>sVzsSe4= zPb(!3QEs1didH$p{W(}cj?518+UB;=dxaY#?6udB2ezfj-Q#L=3T0Z2^CP}d3i*&v zNUpx@1E^X|$`vX6i1e+zn^tuQ-;UPW+`_4 z*GgeGK1RIFpSRyo+4wxxYy^$}Mf|{lLsoYcd~PIMUZ>21-T2^jU83*d26W(j?3Qn6 z@~L43&2o=%2~UGrGZ)r!(t{1f`{8jeZ@!lAN9ky*N6Z+ry&i5Ct$yVsptHF05sE~; zqjZD}pIYO>^e66xK9BTSNn6O0xg;ia=P2H>}&!GXsQKtHq+_?v@|BwZ2&} zNs3nY$w0-~R~}e%V9C^HO|Y(DRmDu|;DXf0DI?~$EhEN{er4Z8tc}0>-3oR^Mej!h z2iOUWv!f_DQK~Js9X>}yxKYBagNuiwm&Ic6?hr6TlgWtO9Et3%ltj10FguwtiWm$E zoAbjE7q#^L!F#d%cu7LMs;U1{IZ8o*g}&QWs*;7)FYrblKx@JTdJzOAg%xTqNB@aw z{BvQw^9!DB)6uk!lu9r_m4yD&J%xK+jnnTLjL|oZ2QTFmJ5UNh5U5F&I@BLc3Syj0 zn9z=xj~7hQK?&T`Iy22xJPF3i{~2-WGoB8SI&;VG(5>gg1R$9oq}wBdh1sg@7$DZmujp`r5;A(|P`p3Dz0)^DVY&DxC3 z&5To{x0#U;*)UfM|I8Q6DcLZ9Z_Y^;hECJrIJcc;Lheo#TXecMo24jWpP$K~A(5lP zl~Lv)_K1)(t{^CK6ssHnHcWHPlyg8t#)NQD5YMc2=hBD?FKopd(*kA^xgqYkF?l!g z1#wr2x~_jR$2?PI_;t@*Lr$pCLbOd!URql=op_Glc9I*Hi_uoX;!suumzJtTwy#8v zRZ_6xVS0imAqjaEH<}&A2_A^KC~bO@v01;aXFuIy{;X6$UoT-u%ztH0WQ7NSd<-HI z)#ei9xQKQ2h^p|yz9gaA@SGg3Y&oug=#2umdbHX`VTosE2NBVYE0k_299_KF5RL<; zTv;9So+6>L%7vjvMcK+}!zBC)ZHYA5H1(|soK7}ICZlAB3jiCU!TTjL`z3QY+DA1d z+ly3=0F>P^Rl>u6nHIH0%A`m}44afey%=EyWvt}@gCpc%u>`VGvM*6;>t4(-RdRqU zJ;pH#j}~67&!p(hJmp_Tn_MPg3S+7B-5CYu;DF(NNie)LxGXprMSD>th8@Mo(OUsA zVdfi4UZ$-Ow9NnurlQBp;wo_<9681+81^eY!)?p=({ZG z(ZtnkVG!P9HS6RI-c{DxK-*d=Wq7zAa?T`1@0h{Wl(8yYErk zV;n&Lryu_x)It4!X5RRpe*9BE{a>6n{-+=R2YKWFb$(b>1;71j1ywQ6J zhWg__(Id+2d<1)i5OcjQ-(54XnVPHe{vXk!{B@^^_8RNu36st-bF{(rOJj5&tc^8h zD;k8W@2D^t3~*W1(p>xkrvSFbD@{r_UnGmxwY1IZWBx}N_GB$uT3 zuKTYo|09r`HL_LC_(E4%<@4P=`cHNB7n{$cMwt+;YP)EoFe{-OJGajCft0jRKl%Qb zlFVXi{r4>P0ubYlVMFe29P6~Tcko0S(`0L-?{H$te(}x8UJsSfJH#nrUMB%c zE~85otbqY-%uc@k8_Cwv7YQO?tD95Pli#NV9gftt44^Z3*8tWd@aQoq3(O|P%$dn! zrcL*AW7l4OTM{u(%JmCryCf;|laS5tYry$L(D^*5N*$xNia)B9T{M*BlF|F{N0peK zXP_!oo@^fI{n^`J$ycs7Utx%t_$?Ap!N$iFC%iZ=fX?=T{;w!D|x{ev%?kl-BEkP`F4V}^Jh4Uvz2+4AMU!g>#}W+z58GrFSNsdLT>WYc5k~C*WTI0 z9jXvAh~Kfid(6*lEI%Z5+WXb+#f=?QAn7UCXeIopN?%4sQwlsbth_$5y&*S2!^B(A zrUJnE&(FPxA{K*3jVp=mu@zZ1Mh@+r>sNY_H_g0*&M0k5F&*Ccp&E$eUm{6;RZ&09 zcrMqYcGjLv#cJuz7pf8Em5>fe!iP7v(Er6q8?~l$eKlpb3?a^~|3~RN{!vpiux@ljA(keN`9=(uwhlJ5o3P+b={}E6c!f=S|ahNcSrZsLx z7M8Lg1%W4~Z-FC&{8~wv?0ldai+lJEdpyr9ijBS3%?T!xElLS9aD0Lq>;?SPuoC0A zc=maI%}Oe7nZs}NLBDiRRHtGFu&)VX*4bfE6$VwamGnm#vu>< zXEoSctY7~??1^IfH|zAToWKDg{kS{*q!xeFjR&|grt?z9LJ?NFNt>K_v?C?!R7zwR z-xpH)Pi#7~P3Ety^aJq>ZqM6P#3(K&tcU_kogEtGE}+Dm$!?R*O3XUDm_B!q&cl_x zHI+%KMbMf!Um@3FG!zm}^`x{=10spp%G>B1n$#=dIrf|>id;F@F2w23;y_n|PSo4Z zxJ%%cug9}!WLrsG0L!e7TzTeTnRUe@e>&U$bK0i`{JU;+?blo<+Pp}sytIuQ`QW1r z5_$n3D&hG75^xurJlZmhEf(WJ%nxbHVO>F+ZRcz1=Id({)Gf1&aD;(Mf`)SLjjq6J zqzn}#F^@}=VB<`&ini}|Vcqm%=pg`>IhU{qX&j@tf2@5^RJd{htL)z$O929{W5V6h z0^x81&2*NedSQnRu>@P#yXf%{nV((jqK?acLtW79S;QAt)PW;R;4nb58>?DA*qnl@ zaphc5D!S2=GDAq+T`buSg0c=SXo7UV30tO4;ltss;@fC?SB~F+59NF6L!m zvsxqyX?xROhUg5t7!=ZAnU{3vWPwA^Qc9EZU-d2oAS8$jpcE*3aYPgivxjjPO7)bT z{3r{n3YUs*& zWY?=y(DOez3a0p6I+REY?p|)2lmvzGs@rClZ!=4R+2iLj4r(-uKh6Q0@Xzc~&7W1R z8lQ-PtR())9#IJnW4PQJa`8bO%9HPRRq^HRu)dE8T8<9uRz|TW&-| z*HTr8Q$2D1Ziyt~>vpQ@blxP4^}Qu>%&Va<7%{mN0u^kewP9ilsh#h2@ysiPsQF8F z;gSg%Ga1!Xc}!svb&#p1PhTSk`xron9- zL!@tChm9&o$my0~>qZvUoNHV6$qg=}<&KwSb9t%yTq#1Ey9oIr9~>HUTh}|8VZ@Ac zeL<}HIr4Y!OTBl{icFL2YAbGU)w~VQHhTU%Y z<^&X?Tm2T@3#_Ck2yPIvLXI)H{As5>L%BHGl;2PIAN1?ypC5hcF_NmHO`Ngy_}q$j zXuL@C){lBMaN3s6Pq60C&gOG}aAz~l;_uF;8->Jr5woccOh&mQM99`-l!zcWKM8w( zbp%o-3h)+ii5255+Y59<)+}I`iNx7WJyz%vA4h_b+Xj?JU?)v2&mh`lRQcj^;qk(JM?zD$yFdZH4nJ8Yykjy(q!sBI zZ0eYI$tQ{JgNzF=_Ii~7r5HGITk_I{aR^^W6)r(ZBqY(e&H*{zGJj=@c%P`b@UUmF0Rt-XN}HKqtp$^;Uv$<+2IcHn_@6V(f#Ji$|1h$7o z2^j7{p%s;>v>?zZdLQi7_rgZTFX8YXVO0Y4R+lfRn55R6pO**9y7mP>1$6$iw7P{5 z%85Fq_ouYlFp{yPS(P)#OnThT6h(z76}J0FY4t-7cf<@r*K{l?C-`q^m0o)%m8qWf z?XH;+-kH0Nn^aZeOjRKW1ka>(w68n2v*@Zq%W`*CMD$|nudYoy5u}h9rIAIV@$Xu# z@gCPMu`1&^)C7~nZI6p* z=}bfP+C{wU>(rWw(>cC5m6Q;kuRcn5@!0Ir`u%?iA)Wq&kkeDe8sP3Xw}ICBA4FRG zMdU>gkt+TII((jH)lj6vO-gJo{gHRHGY<~kRz^Opv~NPE0wh& z+i0#W_nDNNV3v6aSzEXnLNd^_P@QZ|>=dbG%<-~0V;?_k(b*=A4GG$w$5DlFU0-Un zrKbb3i?0g}Je>1mGm%MIVC(6pMTgPIvxG8ZdWx=l8=p~~i@#E@zE70I?FQb!7IivM zv%xygZ7jccV88h8A9wU*?^eo@7Iv;P@8M+Sc`b+k0^6ee_bf{P#ww#J* zuS^E?|HhQAU`#o54e1wXTJTop{K(zCj`3<{Rk!o`$`irqX$&fE}d@|2@OYt#VJH2HI{f(rIH1K+Q)RV1$8CF5e@=8pue0A1Q#JqQA6;8@N z|M6X38CY8Flo#Row_qAD@eRBWsBV;nPZ#|iN=Q&J^n{|IbQ>Vmf*=YBARXyQ@4a^t0wnZK z5_%^z1x1QjK#`^>AYD;V=|w=K*m7>Z&&-^eJ+o)#>@$0>IqN+CKz_e*7ieL%ix>sgINtcOI1%ER#36NT;;OeHg4Y4O2y8*6MSJmkB%H_v<2+c3d_@* z(^G7CP8;CQr5D|Lv@(->WW+bpk8|;Ms=@%1!Rl{7Wy3*`ShWtm*D!yOg?u4nITGe^$GQDe{MF0$oNsnx z>Mtp!lYR{_(Q|mT{rTRQc16BcAA>XfyxYbEm2wbD!fSuudps{abz*JLr)THRg~t(j zsNd`XeSZ!b)4JrUbR+TNvjX%Ol@%tiIftCTeH{0Mw#sxee42-0ubnAgnu#^yE>FNd z{v*-K@yC#}%n8xgJhX3>y1$qCgrUDg5X_B{@N@t#$nudXioY~^QV%h&5&j@JYN?vF z&q2F;JZk%aPl-k}v{a`#AR3O0VKzk^^kVPyM!)5uA5lR3VZuVFk$yaX1&=C_4dkgxHlBGsNn4!EJf6&;e*(#IA~^O;H9NQry4DkPkp$@O1~8)Whi@g*W2rc>iiZC< z@}~c_unl=WxFBB0#2Jvn8y%X`eF8LPY{=C)+=-Cr>T6&rW+0eSGWNxS6(2LIakfK| z9>|kk;%I>`ja6ZEK$~0;k>E@NGfF}HydcXX8CM1I!2USnr659xVmzY@HmmP+9~*$j z#!)79@+T8y#PMK6$t0c#X^h_vN>t!V5I+@PKbeR}BtG&>IHf2uub#9e3$-U%cF&UP@r9(%e zcz8ryVm|e9eu`&>`KBF+d%=WaPA+lSO%g_=(&?2BuUg@H>WnATcKWcpeQ8XkX>9Ne z=v#Bmp4@ZJr@w^6-Va2XCgf!H=1@efNw$eMYShC)IHu>CP$E4jfDn(L{eF&b zyWH93%m6czs|4NyE+V z^&W*J6_Qmkm2sgx|B)HnlY@LRvH&4nP`4kVrw;L;kQ{8X()&p_mkZv|Cd9|7DGLcH zXW3F2ON$t~iWpQOqKM+Hgygdcg$^o^&6YyAL^cUdViztFQi?ifo5|ptMx+`tJ&a@0 zPu^B4c6KS=PjC(B&Fxo(d|1wGgBPgKmq4Z?^d%5uSmIJ}IKMP(%_Vso4oo@F2XdDN z?3Gb&Ve8ZiB;(ot%qE>UxX#a;NiXTuCtEfSaEK114k-enC1pTo*;(FDdYo%m0$ehW z^#cmXRzxWdkVo6u$FjZIaoSw4SdOM7S;Z<4jxVw+bP2@_Y>tIBWgVjgSuir!OROhV z3N%$RJ0Whn1$Ak#m2Xz#H;=|#q`r{?qAxPjBj|OVA=)%aEIk`NJvIv8crGP4+SmxZ)L2O>-iJ!8r3N}d>Un|sTh0)m=8@QuhZ?o9ZYM!O2JN`l z9%L7Y7QXFA7EWsx=Y^IsvqkoXo|HqBOVtFaQmYed6KZQ6N`SY{5D5)vdSWeBlPbnu z)25+ih{}Cynu{j#TJi!twWd57^)H+dOz3oaGgdxmf)>mXF6AuyBY>|(w?q6c{c=?y zC$KzQOzE#g2G%RH-QCtq+|H@Eh+<{q&9f8HxpE^BIL+e3jHAzI<;_d548v)BH&Lyw zKi$>Hu-ur)*rWxEljQ{(&6|2!bm=JfxK3Bw9KV#LjJmh|-CX479ZCKB3`#Im-#z)E zOolGP?>v6gySv;P^-3MC|4|4DgGX8PrIVf$;HNYT&`o78l8_hNz=>P?Yw;}q$NY%> z_xyP5?|%F*@gw}d+>aOk?#KUKe*F4h>c{^74t|st`nw zcC@Aa)0(S8ulbOe98B3zBqQ=pe)`+-x)Qps@fVN6-@m+ew3k&#OEpnD%ZD{to0%>q{sA4vMrF&E@~^W&~e zjFY-7yk@w1OR<5kXhUD&y}^Uj@6WARwl3J7{IHd)B`B)ArSgmoDwA&e;?%%^pXaJ& z@e_5+iyx{5B-K7XG;izJeX)5X_7$e^VK?-conHoh`WJAIj>fMeiVrgXr6Xz5-fH2L zYVyvVq$RTZ(vH=i+VlRSPHG!C*i1;6(oT;)b1<0B4MRym9Oc^$?*~0O8+F=+r~Wd} z!(&1M8Vo6!ZzZuEY{C~r27hHXcZ-s;!!HQ0r4j9wX$6N9!{lFBMOM zP-kLQU_CwH<(qa1;vaSDMtv+^WJps63@ z;AAxAaW@PvbmBGnLtqv0{I^n7-S9xBlHH}oh&MuoK+#hrNd94~4sMk=`)9vTgQ;ak zI&6ewy_Iy=@BPf{u#`#Ts$-E0rHq-srawN}efTkwrU)Lin$btE(P93o)%kR);^(IB z-gc$IV6gLcSx@p4-8*TKcxqPeJ7=#glGn#-uZPa`b9+u-OroB)h8~`vszAC;yf~z> zi#_b4*;?$r`mB}g2V#Z-L=1uvTU5;jbD{q@9{7t5fDbubt&T$MAD*nDNT=EyZgy=& z4+jX$1^dA}W8`OJ901@L5)VFr+~5&u%hn3r;w+Coxp0UFfDnAA9%sCdUulh+2MCYATU9-L zptyc8nQ*2r287^R@992VEGJEo7`q>Qzm%|2O^oa#`kRKNE1u&H!3{%!YVO1lsYJXK zY~F`Ivd#TlYht}P*CJSigG{;yOQMrb0(ZyS6qA^Pla5X#J=sq>qHuFtim#Lklq)78 zmIQFHk2BK$*bOPX$-22y2>Y)L*LpPaHMnY2iG*TE`QYKtH zsTl+bdDsnZXskl2igd~nIjy%kb=3*{-@~&e1CR)canFsiX-l}z2uR4MixIJf8ayym zMt>7wrS-4{XXIoCJ_OZ2lp%o0mY|K2foB`r5I|z01fMd`! ztCN@sqm^c!Y0tznWo3i(1Iy_Tu7eqEe`D5VN|Z7MP({XGRm@U@OVRbG3nXNpS<2EK z&%SXh4TZ|7ypVGw0ef5`$bKT`BQkaemSY_%Y15ughr?dqcerZe{t*pP?TfjVAR$_l z;6BCfNwK5hi3egc8zV%UUbd~LP2dB$%T{T z)B~~=iXtIRA;3a()FI04*=jBsFeJ3-fU?|%Y&XrnYns$T$-mo{)Z&u$1fCq7U^k0~ zP%%(WDX%(IYFl3vz5F)Y)f<&mE(TdEBKX4Z>`F4q+$2yHjS|b0*-$ z_0p@s1w23So-V~5%_;qgs7f;F*;IC>)?A9$nOhLNa=tA$jaln0 ztEQH(H%45MWE-5oFbY*{<*=(WTEN>0!mR-{QZznI4NI1P=(aAH^7J4-z%Dw6 z6G&{W<{GZ{*sFd|Oh%2z!yJ9mR^4}f zDHr2?M9e+YkQx2Fx9^VC7uK@R45Z+H1dM7%O-R;?XVulM_|4W1?Y}ABl>fhvH|GDQ;UDe46mQFa$J^h-zkdw> z{=%E&Vfgpze+6%s{}%q;*&1v4_wn}R`aj@}y855Ro7q3dTi&$%MEn07Z*u<{Z<>RC zo=5Cg{%yS3{ZH^_c89xr+o<*E%t(;%tI`2KAmsAGpCG?(9&k5Y`;`+|gxc?&+N{!t zg^S;Z%bi;|qq$|F+F>)_J`@LAR-|*uF1Q7GpCU++a9v0izc>g{m#H`f9+S$pkDLh_ zFb|5fe)`Yw_9IvK!XJN4r4oQo*0=VNA@U+0bggLp}c-RjRX&jW1THGwIHQ zditStZ@dM>KmO$HvvsbM1`6kqd*1?>o)vfh$X1tQUh{}rn|?Z-^U0B>1JAQ<*i@&L zztc|jFYpy`OmOF(&tCIr>IKh6+ul`N>GB3XDY!j2ne&Bixu(4=@+;()bao%7beSJ^xiA_SX090TgX7l@`mEVj(< z7+*@zFMK{f@yz-w=IOc3j*Tnxr+qJt9=W&vWoTvtPTV&PDO|aTfSRB5? z)-kYC`bPGOXW)6RvG5K-c{Fy$wiwHB^ct^P`{UigD?$rer-640!8Eysn_+>1Z^==# zgsn7hMBvChfu%cHdxWwuKF;oU!=xuF*52O_x4=Q9-6uuPwMH7qBR`A%mDu5;WL{vw z#O`Y^r@S8SJv2~&1l$z$A7jEEW_5z0&%Wuj3-fRA-1M1?5T^%5NC1?_`3wyEw~Cq^ zCRtEuUlutw_M!%Qk%`XqS3sfZMRJ4ppF;x2k*6HOCi zd9>|9Pd$w4CPib_CS%4FVDqzahe8vKv7gj&42l1<7!3+-0u-7pUXF*L;23>61mzM! zaO;czz!u-JNZ8WHLWyi6G$=p~l4cfU$yS89h48zBy9i|h3>B6IL_~p$ih>+phGIfC z_~kPQ;8Spz-5+{F;iTI0`k3SYQKKu(tZj^uaC~D_8`3w zX~ni82M zRMkOt4S^jt(TL?3TN|Gd=X5S5nYXaiEo#OerVL#tpK)sPNu|us2ALmCaoeVWx2ka+ zG?$c@lc`eeaxw=gbo#h6`wlYB?j2|dbTOK9D(lO3mPC&)7`D+TxcQEIaQo!Q15g`5 zulEFryuNJ9x$M=p6WO9U2uzNHPmUWU$0F3rjV;B7!ewVh@LzNQrw*JkP@p82TMy?s zm1DS_Qx8juH6u4Jv6sRUi$f3zHC*71g|9kz=}2m&rlKXRKcjgjap^5QmkspeKKE*H z>Qi$2V*)YIOpL23Q^sMwrkF)O$h7RDz?Eb`YQb9A+)PiB}m8U?AzNbhYVb%+*N7imSen zc6nu6m4#z%6*Xqrhr+6?Zbui7VQrRuD(~wWS5r7W9)C9xR;ZA)rB?S;Df2mjCqu+24)zzwN;C@5cK3f#v_E1Iz!H#^U>%u{K=C{{v$={gbhj zGX9eR+1Y;ImyobdmHvF`BQ4$T|iIoH=f+Hqw+s%4wyZhf&yvCp*s%%>6Wjf+jx~40??JLlnk$ z7=`(PQP@X0lKc%loz>X*t7?~8FE&G2*Vb`7aFi)cvcRr0hWv^*@#>5UD zP1>x0N0XIzpQ!(JH2GM`GK^*Idr`nD?aAuQO>4FX3XcURby(lef7t9Ilf*aqFNc*%USjzZu4o@NLD96HUQZ9bcJ%ymjIiJq-1L{qfHaXV>*x1In!L9754}f=R$rx9 zJ0|4rg0O1db!2_Krt#6wO-yB@_HR=X8ZW?7CK|^Mn0dKI7j5?hBz}!P#FWAQ>@65= z*;6mw^PS28J?8f)eLB`J8&B7eb`Mdl8$C>m&1=u@yCG1^ZhxGEQbfQYzDJ(6rH7I| zZ&v$)Y1jGch>gD*KUw##9j0A#k;6M26(;WYeIwvfKE6<3eGdz!UG1WpprytaIX>(~ z5_dV{o#`(grd<(Ce_84n5?UV|6P6S6kCuw@W5Zt%kAbK}t^Z}IE$8Td5&bby{Dmdl zz@epL4=p8yGem>W^5Ved$ThI*voqpR48N#&v~7st7lMo z>lFba9=!bm6%|b;xRVONb z56eWJ0MhNA!jhqrApyS0z2Y%AYBHx(^pN=BgSTmF3XYuU6_OGb2$pcBerW@T!QeST zsBR)#5iB)DDD{hCsvjZsP)?-@8~fMf4|Ud6FN5q{EcXG1nwR+fob^0*{0wcDW>t7-XdQXAFoVpyDyQyM8S}iJVeCYlO6u za4BJm9f|;#7ffHFF=ZentOeVX!jM^((ph7mnS!!*s1Z8qDQEk$l>3vwH*A__DZP6^ z7)+W52HH=|V4TY4q!<_M=YX&DpaF;G%A>^7ig?Os8dS; z^Qh2}B=|jY6)Jpek9>xWvLVLOZ%P4tC}dPHy{hX8B0Pt}YK8)W74w7+vL!R}mZ}gy zNcfZ(Tm5oWJs3uD=AYjqF>E=Ano&Ap@nl6*9E{Y7VS5HL2^XmWGKrQ^utDNi63cg! z2&Nap7j{Psn6dUs!)Eug-cb;N6?t@!A`nSm%>F`BTu~Gz3yles*^mC+pN|K^tRyn` zlnNl&$e%TcsNP^`R|JV#0PvP9Q2=lG?DJxH!<>R#bYZ=GG0Q{3tNB7U-Xf4kTmykT z=7}V-t(FT`XQ6ZsC=){74nmiU{>7u|<HSyt~GW z3Xw1qFr<>WXrYmZc{*+p&E>~k%Wis+s8egIH=S%Nl?_2S_jld8lEW`sYYz~-EECC@ z`;|GIRbUyYok^91YGP$u>DAV%#lb+qn&o#;o@&#T|1yN)23UbkzzzUlG~gd= zOkn@k3$#aV>9#w}o$tXB}Qw zn7kEzQ;yD(4T-_gW9pAn~~cwOy1(dWpQ+zyf0wlU5$R-!b=r5vL9Q z@Y;<oX^8mfFx#4bF+3$8EjuRNchcdB-EiU$6ljgdl8}hj5&5iwQt7E zweHVk7pgM%k8pa%;D<1>+31h^?rKCWv)>ho2!4y1y zqr3a7OM}VMRHd(4y`$BcT6fya7{O^D4l_~ffu|va6QNoc1j-_lB*ujSecdY$&i0sJ zX;gOd9Q+=3t#{W9cpyhZ9}ji1cvWbZGPT9i>-DazZQSqMnVHW0S64FnW4WA!Ug|@= zxcrjketIz_oW8UF-XwU)-_T#{!-Jtb%%@ql<{A2?1-EJE!si}_XCE%re15B1aJBM| zoNBO^M1YgS=LwWo^IP|y-fe~gog3w9%9{@MQ^S{T}m2)R- zj2^lE<2y^c*+egNkQaNo^0ARg8VRyF!S-zV=)piMA2US7bE*7@z;%rimn_c)Hn?&q z@|%+CP`Wq9d^2DAe9H=A^od}oXZAx^w!Dx%t>fWFr0=hM-2S`UXrC%Lq_fANchJX* zEt`BEQ!ag}#1Si0e=LrM<>KKO5R3CQw>`>KB{$kX7(=hBleQ)$eW|VPYK#zDR7_ho z|INyC!drs$If|{U&8Gxhw0mEZP19woq-E6a*v(Iv z;$eF+kctm^ae*lG#*kg@;&%F{;ghpF#Jc)d`sYisj;m5N&;^%A(%W!DA?eVffL9rr zSDL<{-rAxcZ$3-&Dt|6o<9s-wp4(O*e{S6ri9^G#rd|Imp&!b&{E96FvR`r0(k#>T zo_BBnbzajzbda?OWyn#~7n=v}=Uw&| z0-G%>^2T=9o}bL3F~c9Predfy6bh}Adzr}e{$ zoE3(`ed>mgp`4&B?1++!Qk;+xiQ7>I7?MzXaqaEpPn^{TW3GVLu)gzqPQp?89MyR6 zWtOC2rIVI~!ioOTn4@x+9>vreX44tmHL9&{6K-86ct*B~oVEU{LF?$UTy(f39(+j+5fwWcJfjSNeZhg{9HX@T~x ze(qTokFQE2Z)nVtH3>O=7Nn+%(OaXH$op>Bt;4G)B>^jLp*l|?_V|T|FQSNWPrI6_ zk*Atm#p;@TVetb(d$88#x+`9lMyJyqMb5N8xU!;}7Y@#?tE!C{Br4`8Ay$|_ms#Y9 zDc4=#x%2)@gRcL2)C>2T{yb9IrQhy0IX^Kmtg(;Rujm2dDsv2oL@|lM2CuDYpCAcNgnR8Sn~SO@BqXJ}5$| zr%S!00)0t&P3x2`+TzDvu{RS``tvQ$KXYz4bMgs1*V%a0efr@u`hM+=Mc-(}(FqA` zM6P@VOQWT|&f?VD$nhp>xQFsna8Zftg=?Uh_8ZR3fjizTtX6_}_KiQMl1hAQ&b7>( zR5Q8oy0}>tIj!Zae1zdmCo4AhcL8wDUa>h=PS`b{`IGBA#zC>;u*i)S1MUY)4fXwQ z>PlMUA$6w&^mF~HnCup{!!P!(I_*&ze{)pQnKcSJ-E_!J87^N_06zQgcsC8K4Stxo zuR*)HUvx>pR(VxPhD}Tjh!=3F5ZujTj_a#Q2=iNYGU^oW{d)WHO{@F0!4u2MttoQc z{xQJCCz_aA{S!4qp#-Nzy07~_8s_6QJVAo!+o7t8EZC}J!jSddq*rGW#$)|%zksj@zb8_?fp0 zAHwMhyn>pKUE__v9d4NFYMLc^oRqAgIfDsHzn?d<9scn?3-h)sU&-&ao4P7W1FE=Z z9G4V&EGw_G^Xlc46ji(+5LXFGY+dMHh=wd0uU#3&Bj`2Sj4s!*8@SYHeWpfjOYnW@IYhtqFULb z0|MB+zT6B5h{j|@|E!LJNQFNXW4UYR{KUk6cJy*bRrF8iC~(SvdtVaVxqH`&%X^DE zfdmA_S&H{0JLjUF5@IA2Pw+Cuz-MDl!tf|qpe$MijzGCMM~&#k9^UM2@||?SUPUU- zE5zO~jqPw25Typ)?7K0~gw=P61;L`)7i&UQI)S#u1NOF?0T;OAEwcg6g@{iJmUOuI z7iICP3;^eNyw_5M>mGLi8ndDh>k&eb&5n;mUdzZhN+c4o`*9aci8?eG@Dq`cNhX3y ziRMPxEP+d>s7&z$9p{ATamx(fm^^XuKh9vdlaLV-R1y+pE9jL^N~omr;n0xR1Y&Jp zOi7#lr`>pG@ud4m-UmcN0?eOHA<}9;-Vd3Kl1b(iMZB(#y42!TG9K5mZymnR{z_c% zH5&3G9xiW_;9?R9cAGq%B)${pouPV1ai=yQLmYevo|Bd@$*IlaX>Zy>9jooZv#tg- zG$@4dIyjZrB`v-w^$e2VTpjXkAx)K-Hh@lqCa|%f!@RDu9ZN`CX-(S__qf26*rf`A zD5Wth<2gbR0om$157^MAtQo!pzy~egn0`^-U;e<^g|^6gN+NS?7$57BUeTI)W;nA$ zj3o$}1xRJdVi0TGsnQfy2nsm0bWB-^P>IYg7G`@`q18(YV^q!V&nNBgt$ z6>!p1nt)~6 z)7g^5_I$-lN%IJBzs*jwKkWdPCQ}{VZp4x)k%RZ~Att1%Hj~Y!$i@T`+noO;XGF1B zoUIupH z6=LH|JVksOYS=%c;^q@f7HbH$KKX4D{`zrl8x?VX;LhJLd1$-hw084?%HsYSc4pqV zdk4M{w{V7wxcj}j0CRDB3wqgx`=5t1{GdIW|121|T^eeQe{9d+bNn+q)pY;6rxC!~Tja6I z4lrS`^u<Ee=y|XaQhvtLXZ2I<%?%2f4z@>Bcm*|Xndc%H!f0xX<|4hD`uk_>Hib%_=s|=D0 zCp3F}O(@Q}@C5-TZHSabG)+lt+SNP92^mRWDpC~u+5-U?Zn9C20Dt&Rg=~kqTF1gA z%NS!*=^l>Wm&=Ed|Y*dGgepERHE}mHuJuH+Lgzi zn{S}njI+sC083PPx+WXgbRn0KTWV^TLeV!f@Ds92r0qaEbAjt2m1KuIBGVc{qhQlT zM#|`d0l$ut7*F82pm`|Ym#Hr<5xcHj0YpZ|+orN(-7hJ^jGGQY;0Eau)Y!n;k(iOG zFm2~$PRo01`yDk-1;S9p}?im=5-~Tf? zJyfEGGta#A0}-3n$c1t~1KgHe)y8E0V0fRSs-8dEye`5${@_C35YA0t>6=5=&6V=I zRBpMtJ9MXBJHBZT`t`*MqwoP%)qx)Dv$lFV=l=CY-SW?~pE(sO zNR~?%c)B%E3R|}}txQH<@VLKUCtA7v@@+E>RhWqFHEt1PTI?B+iP?GlNMdkzWUiU| zG3wpfTacxQZ`ZSN8r$dJPl*)`YrNqp#g0p_H@|IR;Ct}&N4DelF}C*c66gC8;zc30 z8ubEpNmI1pi5JfAPKJ!Re>__FbieU8|LtfJ4L-aN}9VNQS@3h7D$5RWJAOZx$x3%X?{Hxci(cO#}Ic0HXeR=+;^ zV6mn<;ni`r@FyR|G-y_b%~5S}nbeo(3&?L*Jc<2e(Ko%d^Uc*HrEQ0$Qi;?9Z3o#= z{#bS*B?mGz!Pe=ydu6{JoJT>>^K_HF{kNO&qt{z`WpQda{|xg@w5)(|0XOVgKZoQxH`p|y4F}tkXTdTy8qnl&xC5x4Hpw{ zHlYZbW?vOY%g}A(BQw*&iipqe`&e1;t3BNPtaxm$fuKmqFj~0A&T?{y=<(NJcTd3N z(F8^bd(;VfVTqQ{DLx(r!VedOj@z+m3Y$ZL*9(sZYtlSh_6shKZe5y1Ii$}^^b7J} z(3_@PiNW0%vkyel)bJg_rJwv-NG0?;S@Fwi-*hg1K=!9-`z0?Ug{?!Hdhc5q2vWdt zHYdzWx5<0Hc(y+L+H?V(i3;Abb2!m5cfEol$*4sBJ@WVC1wR*H{c|tkwXhsTNmtHw$vdVOF@G-a5q2$BPrRwl`#|u@<>}8~MQ{U&>MW7Vob4MY57lfICm`=&%7} z*~Fb~xq9piO-ZHD@vbsiAj7rKzI@r}`KQ>X#IQ9NgVS$P?Z%bVxazNuJWM`GOV}+H zFGL!hiZNHJxdr)rk7$yDivPs=MZ^tNV^bPx@JJ@GNQFH;G%S&K=3Z>m=e%l_Bno^Qzh1=7F5WmlZm$;6i!=#jZK;33BGc7rWwywsORhaE*mJ7dr@co znAduX{cn?Pf37PH4g|IM<$S%hl>hFaD7P81dEN`N`Z4)aP%Xz3Q*ujnUo`L#n1&;0%tY`|nDu>EpI=DEQ zGZK)tP?+V`s;Y{Z32Hsky~1`(g>FEfmD%O-SR0$@hf^|oQ3IK|#~)n2{_NsF^z`gE z28>)AM~Pi%Z{ZdVP*JLQTxQ6grCmU)ygnM`G}d+n(yJo_aHoYaXP0l-KfWYMtL1zh z{HK^V;UUXD3)ZJwU2_Oe!1)htgI;j|g_fGJZB)c# z97Vz4eDOhR+E2j&-za0a1ESuUHvIlr^o!HVkP)fi+E08>nL>Z`%EXvRx9mj&iqYRS z1Xgh1t%}I@I(qzaUdJG_HhzO z`Aw1yUeM0A(eI};ULYHQ?}qj|SrWwXmyt2>UA)SEsOkjwjY+kRV4QMDtW-1pCQLak zpvs#EEzpt~g?>8O)bWBkVjf_9E;|MhIUP z*+#E5;uaxc3B=%7 z>ORqmnq=6OpuNdO;YJ=+iMZj0(cb3Iy$9za7m8{Gy?anD?cFDeta4O2Ku zBcG2(a?YiEYzv=iOL3L=_1Wj+1X5a&sqLn5K1S**57@q$u%`LO0xD?vbcYQ^Uucb! z?;`6C*+yjU7#lhcACmgBkNtOF$Ow=EfdllIbO{B7YkW8vk-n^w2HC_O>rc2Ko>3so z*5aT=ZVhJA&qyW(0#aJM65j76|&}s_`q?mJ(#q;Yz7@JdtJmtqAUAQ4pO=bnDi2K5_@ZevvaP9 z5^P0E(@H}4c6+8RM$aB&$2MoV$z{wa9W0`lKtcJBKabR^2qnbEGehP{n~dnjS@s3z976D-*9 z)q3E&+#S>I8q_E5N@;B>2)$vI!&r!EWuL{w5HNNVQ$f?1sF+~gakGM7^M;@MIsZ8x zPJ(!#{wMIDY1tjF98a}TiTmTlSMhrPXL_j7)>y`{UUVoqe22f)669%RIEi@DQd{#8Tiw6%`j z-AC^sL0_Ro)9xQ0yr3t~tNi@BaEjlQo#yfC(S?n6v%sgu9vXrxb61i`^EyL6J&HE$ zPoLNQ{%g*W#z35m5>L6o9)i<{B7^zCrL?GDaHzSfXG&ETj-JAJ{Ll?pgLTG3Hz1Hg z2CpBGxWYxtzF68@mVj>PnEE_t{(48gOhBYaam>_a>z=k{8KZ`^@nJ)rDYMU9#a|71 zUWW~NV18qN3@~U}DmT5wsFdZx6~mZILP;-I5Jdjm=L2rhsT5>eMTK&@9G{W~lZwlt zBNTbtHm3l~HVQeL&qJ{K65W)3b>R&q=Ski5NRhYNk2o_WFq+mA?0~x$P#K^fM5Tt5 zio}anh|IOT(~aw-tz@I~nY+bR_upUCt7by=-6%`A=E~$ml$~?6j}j&L@0Y$ftRCY4z8>fQ98#*`ApQ z*d>mMXA-C-pIht38kybfCLZeq(_4>xTQq%nCh#wA%A-PN?^qe3%R3)8r^v@1uv=!-^>OM zHd+J7+%sALns&M6ELLMi_6eO5;rw*0)~K`%?uz1eMi3A6tlb~Pn$E{)de)F>onV#w z2CmiX4~%Cp+uzt4XY75xyy_7X=pw&m!!G0zz=k}hUCyvkh6h$$%Q>D`ZaXzMrJnP> zd;7`GTJyVSN>9>oj)e8{#a|bg{I=(%ohJFb-zNQOHf|TtQn(#7N>KYaMD{iIK-5C| zILx(t2Nh93#ECfzC(H0R=Y2yjY46WoV;X$i%c^t4$}L1%G@|>3>r;CD0HTr1bT^aT z^OYjn$?^tm)B--|LRJ-Tj7rkY^PX2qbLqAE>Y9ua)lmsM-~B(>X7c#aMWF(bDerWH2Ygjehu z=~D4c(wE)rE{*r~JYhJWs913Fnq}KjAUP#8Pwn=!$DC3iwLJLA1>%WbHTJ8#+i4#X z>}I}9O4ij6pA%@aSADhEp3gs$)~r7ie5bcCpgtpmw%X6zwWQIp`7G5wYeq%9hTXPp zJ7*tjDBu0pnoH~`?jvL{#Ne4FLmAwLs@e06VJf+k3UOA4SZBj6dcn8#@Il`(EFpf?dX-Q{sw8 zE(@y&NexEabA8=+I8ib~5OMRym7hw397?^UX-=pP=3;g) z`0o{6upJ?ottIjMb*$cai#jHGK=Lxaus?_jJ51s-FkqplBM18tf0NS3-2s**x=!1qjhIkZ`aov3f7Y?#N*1dDvxQ_lwi)f4@e ztQhl6?pDp0cOG3+9pJ_G%62!sG;*``y*DYRBrjX#D5ie)Qckf`&`C!t^>pQ*qd_#f zPFw99v}<&rIit_ZlQl5BPmaXV@so`Av5_n2)x^=D?WL<<`fFT$!n0oZ)fLh~#-ECx zd=DIsJWF`#rmdoFDb&w9qH?=B{lXz^{Fo7#Pg*20P_z_`^@B~Q=3 z4rB##gV$zQ!w+80A&A7@0#>R3Y7iSJ>HGGyam~5!k6O4IDEtwb1%92a3eC-CoO&F5 z3{%goL}4X({sp!)lchJsF0GXQy6mUN zw~J*L&WDXzn2c!h*Src`QoUTbhTECC0w^k?V3~lC#(ec7 zX81C)3Z}xA>kJwxeri2_^CGTFJp$%i4n6#@7%{*ghs`%!wmm}hY5l1K=JjIw$gV$8 za>H`R1Bk~9M;V(`>Chi`7=&#QBg7vzcMfjU?!8aD^)$?=g;^`*_zaX$=)q*~IYiZo z%K%(lLrEM63?>mso+RSc^{D|9r|d066YdL3!W#A|)8Uf~TC$ks& zy0^ZqzB?XH7kkA4U?}>=DNdLsz1VH(5Rj-;_>E&>_vahp0~?4tzJ#AjS@Kans#_fS z#qCW`7C9r&<9+0fFk1Ko6Yv#Bg4R5=+>gU=TNds9rhPT`-c`+3`&q%>C#XXE?HCvR z3(FKiSAh#M*izq(_r6-U`DDE(J^IfAA!=kevbQYSDhv4I9E25PIjRU-Xyse1j)3+_ zQf-5rda*~vL+JaWI22{MU;vVcJFE!DV%aBgFJ+?WJWs@o9@k|bJ zekoFVQVx)^ku}9<68znp@b#a=xE1lr`$~-H*vl}We=}A$BvurL*LD$0X*y;~j?)9* zkVrYD_{JE!@R^X~OwoQ;icZhQko?H_mqHQX1hIo@d}MHZ9S`)Ge2`6FyaCv6AQ-BP zBw&N%g+)E&mtsPx1dT4jRahJ}*auFtAw-H>Dz(KD$=r#GHeCzh+Ka)kYG+|&0=6|i zr;VUYj@`h)<%i;&6ddXn@$!lZV)BWGz6oIQw-6!GSZ9`VpcJIo${Dj3XH)3eO#5KqiS#YHf#b?1+bq z4B_`-09eq@Ammg>fbWx82ao`rY5K$MNLafY8=IEzo+d|Addyw`Fsq4Z_j;?C5wRE^ zKZ+bF!6nRLr;th~XrX8(>CBNhHc^R?$Eu!eX33`rczQ@yd~A@I8Ec0$%yBnqar*{b z0^vK6CBBt)=mZ-JHB2hGEfKaD9!SXH1)VU9*>K@AfM-H%0&l_DP!oPoTo5WG)1p5| z4eU?2l>}+@dO|W3O~CEDpk3fOFH7wN4|J1ry}8*)>1W4800BR{zm@PO%}mr(){hrRE7^nr9HrJFvo3{k`QU2Ls%%SkbidK@kE4@Ptg^rdhj9H zZ$0o=Mx>@0KPVgm_jrUJ<{U0XVx|$)2PO6H&ed3=w{g9*bZ<%@I30>;Wb_MpPrM7qEG zCHW*{W%GOO&GQ+d|fM!IjzZusoaWf4}81B$T)@Fr!$!LNJ zgK3LP`DJ+bsir%*oa6WY^i2;HtN330Tf%TR=B)S`z=C)66*_gJ`(5@G`K00di(KPl z%~D{(;3}|m-ysvTVt==qTg3ei-H9iTZ`y)3vuDs3UiVc#lr(m>w(J-_{k6M#s$)I) z<9f$g^_RZ0(-u$9F{`=wHrtu0!VWgYGqF|k1X8y>x73#lv3;+DaEkUNw zEs1`r&l(~mUTuR?sD9^_?-?uq<}#bZJKV3Aft!J1J45K&N4EmdryH8jK9+B|t89DY zY~b};0qT@HL(qi41WPp|U`v?FnCP~9NBa~ExE*OOc(Pw`MZY)d_tw8lm68sIE`IP01r!fYzYiH#HD&g&UPFnGC#Ie*4fZ*Fzw|MnImm1PKQG)v*v zMe+8_Cstzp>+Uw)xFUQ#3r;hmp6~Ppzrgh=;Z8(II9*qpCs_(wbPNo8a083 z?+R7_z=|?{ZKY%1r}8Ig^qS~brUdxTtTNjv56&=TL}w4;+P>Xit0+%NF|sq57Vo(_ z62}w5$)_r5#_v^@%ww(#J!N8^v zXgFqH25btG;o6y@!cLv{-Zr1_H23m1y6CbZhX1)K*k~wyyISiAYzpbTPpkRb=%qgb zXS#*Di-+_eYWI7ZdLL_Fi>}%ekfMT1_ADMe>`>8-40ORNnLXjfmR(;rhKGvseA!{* zP5;ewjgVIyL8#Vsex?I)C^m?pz1BWDhyCz ziK?+^-nTz+z)ql5eFIy@m8A2il=AyS^=}lQRDeWcxL{V$m#=!2 z=_XTa4CI?dq&5{>FopB_sc2y*$w2@dj}1( zj@6;=#$&Bs5a9h^qyN_qqWe){pb5)eJN$q4M6*mwj3NP4jWAsT6`^8-~rHx6srdwqnO>$}> z8bSEs_}uKm->-qH*VqSA*0xKx?`|){>12&wXHsyI>>6^NfiOJ>Gg6iXA0$sqwn$&s zDD-SJI%Tbv=y9V=o*wlj#%#8g9gt#@=L~B~UNXo3Q02XLvBBK-YoEIE?43|tLGSzf z1Q@Q(fWqWo#3ASJWN&=iC(iRV$qGFie}C|bHWr=}Ptg|NxE=q+8=qk{?o}iN;9!7B)Wg9H z6eC>`{$|#Rrf7NzC^%LJWi<*jfV*`KBN=v*oNee`p$T%hTki$oWTQw%94ZjXa0}{! zHyx1^;nw%fn@l+QLwEu{E=9XFg@NYsUU2gQ9h#_sPV7pCqtQW%36fo$u3Ko^dKgYI zHKHr7z=u8!9xLGO#?YH+3nk)JOo-JQ_en9CPwslF@1sfk z_%t;qBF!T>-F5huK^GgtR2r+WLj_Kpdq>;7-AN!MZnFi#M*>24;CJ}A{bI^;OAZ}F zrSh#&?+ImA%mRcS{rnDWhCAUM325aslYl26Ycz9rDh<3Evoo6fpg#-8PuqGD9;HD0 z86F8F!5?U5_rcP?qhU1>&~zR^1^_vEoBom)gASu1DsuY_qb1#iJyCc5icb3p3w=D2 znc@*%Xie1(4g+>r7$TQ5HER zj6!#a5)17lqot%Ljn(&fGF`J+9r(=-bg#BYO`$pIE}&1;DVNPts&L?70hygyF`Hsj zlCdPG@xL~s9V6YGcYOtio!7(S!dbFEVyRe383Q7rL8Q45K}OqDgo>`?Nf(lohH4ao z)(Q8Mn8SH3SfUyV1VV6$)wp#{D{_TGxr(CW@3>oxMS>6_Ab9cuRIdLv{!0SmKj!~G{*(XL z_)q$ueg`4_PuMd;$V_5FqC1bvdI&Nt<2eSu(M81yZ_ z4VBI}BFstS@fBSi5IzxGZ=ma-6+XWe#a+p<5jTO$V8d4@s^W374!^mU=OEAuU5EP* zejAXxfW6UyY{&GIW3>Ttm!)r?X6z4E2svHEiRWXaxz<{8@49`E^QOP34TP+?Uc=M< zd56qlKRjW<`J=)6$BL)9>vQKz&hyVKs`&!9tvzBLN5F`txrq1i*HSx5?aFDtE~&W( zMwDG;BS0`j{oKVv+&Gtj(}wQMZM~9#B?3u^v=H^;tCRCy#>qZPsFD;ILU`TRJbZ{e zEocE*3H{c6S;dO10Wlkhu4b!zoA2nm!N$#q03r>bnzU;-2@0}hB8gnB9Ycz8at*vl z)^Bux)dWDGo86v;Od)S_IAj=aQoHkDeP1W~%8U?}B&&D#5e2g@ER+Is%R3j9iV;f# znIkiF4IhsPhaIT88=3b~C6%XgIou0Zlu5>q3shm85jE#=y|}lRlSWm&tNuJBWT(Pt z(X^-nE$?&hMsDririBvg8$XSx^RNae>z)RUYNyr7(gTpoS>shcfqUjbCVM{OH(h!x zS7aQd$$=XI2DlMGS$(Tj4~a~gG%4d65y?Rd15F&)92Mv?q`Z_qsf*7LF$aBm_%Yb` z&}_*u;;UIYZ76%o)|)G7j@z7llU?D5ru!lRj8RjW8!ZF0`i&J>TKj+li?`ia?qH01 z2S;ap?T?bN+y@hq9GXk|5|3t#7}X{ujZbV~Y!_x_(MwP=g?ANqv8#(U4dBEdS;@J#A z5eMXDuI0fU&z8(M*ltIe)5+fbB^jljjBwACkHxR=UnLIS!iIQG{fv7PCiGy_YI-QT z=j8pU0z<7mEt`cO=s0XR*Iw!-5y(kr!>eeH?}Dh;#h=oPm?Njrn|KB%MtP+_k-C%n z0LJEKgi#|ZDGSq&n``4719^!2qD{8(cx<6@uG6%c8Yna+%1wOBQW7~hN);+&(;GY> zbq$>qH~fRL_F-*Ln5|x<&X?60$<9uEstpCHhZ=nsX4UOI7NaV3vhTx6*O_>w@5l2o z*b^`2WQo>Rc_R7Hj7{}8_L_PQ7m6yU&gHPq4f8DOX`1Og25K!72@YOwHGM$U7FJTm+w@%(D> zQE>rZCQqvBqB#;zQILs<)4ohGl~|q}e#^znKv-T01GrAk{iNCtmh1wf5ms(IGIHl_ z6LzunlKw7ijGSq^gHOx4FGJFladKSTFzR(fL(e3d|KzSZKU&QkX@tB_FEpC!c{QoR zES)Gx8bq^uy}RG^D%D2SFNy~FB)^yTG_x#RS{2XJEHPLzRK*ofjFHDME$>si>ka>)chtq-e|+u9@nZCZi%)x(Wi>I3(36o zJcT|~ClmrPz!uORR@QSAr~pPpQ|v|Vx3=McJ8n8l<7sy+>sBXdU1tofkB_(SmcEpQ)eSThuNa^c=SKm+leC-rr0biIjM;STbtW@y1~286HrFN%dE^>dv*9pEI)0 zyOWk2nLfT>y2m7IK-q|yh^A-TC+;WqI*g{K%L<0#D24^ZVbnjL9AtfaKF%SX=Ev&r z=(Iu5m1HFCLY;<}ym|;qm2#=TBC{_XdB%_&_vi^d)yUicS5LWJshQntWr7ePT`i0; zyCV{!1kw#^RpWiP0f~;dXu7Ln6)!?IyOK~?uX(Ur61!lTMW#5>(4wBs7PG}y7db{3 zblXOqY@6bm-@x*6U76T~A>|5YJlpZW-YhZK3BZM>86W1p4DjLSQ=T?*3i7LB_pa-i zYY7by&yQ}{?daue&fr8x_4?s6rblsWp6e9z{90%3?5<1-40mg!@DCp?o{kaBbc-RM zYNHz(?3aIp(a79l604o3qv~z_{Pc|%AJdKIJ0hBUzm^Z}ehMNvVL2QVQo(sh?uJhi z795UwxW{2RM=>2}g4mseQWns+;m$mJzo4qFFYlxIH(d<-gMM1E-6i0G=Thb(t_pFl zUHYk@O5+2cm_?~CZut!2OCEkqm|edRM-LlHd?8q6+xPWT65 zA9Hoe7hn8e{RW;TL94_U+yQFHomLW(Gn)_5Wxq@r-Rq@rv2 zR{S^S#G5{Jnl=cx2;_UBAn%d5^N4u1(?ogNBtl^tw~+{Xs{sGuIA97l6GAyCCQ=JK zKL&yWy(p8qL^EM~J0Agm8+xam`2@i4_y zK6-7dSx14RsLi_&LK4tz5BwrX5RN-&T|V{`O?t~H`^%J+XZZSEaQes4@EJA4GZIiQ zB!i&OBQk~b8IB4A0gZQN(D{f@c0uXX^|XcbB&=zsq2av5pbC%7q1x01pWAo0({YJ$ z>)w#J#A(B(SX_|mcZX0fvbbEeWf?~}9O_N2MS9QR2v zm%kfBI^{+K0SzU?#pbeBQ?f$|^6cUCR<%0psR4wxv`S+^fIE3j!Io<-o=!f0%_M(l z7|T@?V>gy>Rz!8~LuVSPa}<_mJe{{IlsoL1`CB2s5t^(d=lh1gQ2)$g8A~M{NfW4~ zL*Q#@dsWu*U>9gqd4`sDxbR8P+=L!s8}t`nRDa$(oKeAGWS zySE`QRizWWs(GhWx2;w;Lh*Kj|86el1Wq1B#-S(WZB%gG@jPF*y}>+JI|PU;H`l!? z2ja?$tg`o>@VN}Aa_F1Xyzm_V)z{{pBDz=uVh`2wwc-R(cj2>J()8<*eKu< zhykk2m5di_&=nvupnDk^aISO0Z((%6`GE#fz!OO?Ap0Lc&p$Oxj;|e0J-29}0;nIg zrCykJ`3V{K{)e&JqQ?(xt)0B#V6Ruh63SwZZ9Vvjn^ShTHu>1i=&oOn;ot9VB_6oo z3(#@dSvHME)fi1F`aj+F~7*$Cq&yK z9xo}0Bm5HjG2L9de9GT1KylD`~wm7|(LLd2v z@ruAhPn}erm)k%_Sr`Ijl==T;l&@Z9lwB-9lk@m$c|z;Ln5?8jyw_foL60m8Ryc~P zlQ_<=vVlzTOkDD8{8CN4*cZS6`NK~%gOmRn;T7souVj-4WR$ls#X}->>Oa*9@++YT(y_wnJd(mJX`)|SiI!3dpvu^2DS!`-)t=*O-Pxj@- zS)b1O)j9Uex>>LjH?)2ocb#ogXt^4|GGX6ufqh#FrBtA3ZD%$j4HvhZ!7Xds_`_#=PGymz6 zy${$KeVvWD_(2P*TbF>Fo%p8RiqQ1?PEgvV{#4|9^BWBv$+Ha(bP@fQF1-cJ z)KGuDJPM-!W^soQtGcwSL45b|O5W>|c`KNUlZ2-Chy5+b?u&l#Txc!S%`Tuu^{Lv> z#}8A50qPU=*YR_lBlH3u%|k#iF4rZG*$<;7?~plNOdL7o-YL_#^eq9!pYG|?J}DI& zr#tRVW4fIy3Mwli57hGe?S6;y38w64+l`Ui8;K`TgZn2!m5}-A`=Gi6@O^pmHhi0P zYdMl+0ttEp<{FH3JB8pus0-UFKI1&^HJS-csD4S}#k;Lu)KI2K0O?HsafEvBbmQgo zJ;Uo(nJ5+ypouUe(_l7BGK%&}HcREtwD~8Y68Ino`a65M$x8MXMjU&X<$VggkpnbA z7CfUWe6Z`9OahINW5)Q01Rcy;x2bSsqPss{7)Pn85Qk$-iS=V)Eydv^W}gjK4l<>u zFQzpicPTvOv`Mv}k$9+m9IImBTPRyMk>LPCtCb~1=nVag!@~}%4bA$-o#ef;_liuo zJiA}Ou6yRT@T0{Wrv(h?1`AGKvpoS}$dHG}Or2d@5(Eh^(@q{1O76XNHIwGXAVc#B zd1|G9GGK+NJc{N(z*H|K;^%AES`D>~N+kG4ytjjr^DQ@Wf=Txt9In{?4A!%;&4YE~ol){y$UwqkdEU z$gpxgMj)1~ZsHx2pZHtUO5IA7BKcXns%egh7Ujd4t@~tk%8a_kv3B%Gv)zau&3n2} zSU@I{mKF4tH4Bx+R@Y}vxGjg$aP_{^A3^}piI!RV&I^4mE8#jkX)(*`AG0#r76rGo zpqBU;T=LlZ8@!0UPQ?)|tgI4B_*ho^=-7F=zeOFVdhV4c~|ox4Bz(*2s>Pur=e@F#~m z4}9I}Z_M3es>TDJ;fU$7q%cSdQkwcG$|0w+XN9##L+;9McFw7Z^749L_p-bEY1vlm zde12lh|5u)9Y^urL5iG@VkFGqVLy}Ar(}H#^Oee)ss_pwxE4@FLen*CrTi=k%@Wse}`oT=BM}#GGy03~DM&jT)7ua_NCzMvXE33*|3M zdCHzIG(CbO^U9NGgoLwaA%oAx%cy!&Q%YSxJL|J-WIn|LF=8G4xW~1D`u3m5W@079 z<2cV-3REQAOqk)bNXc*?b_$a|nMX|$PX3xXO<9Be#WNL36r~roxegbR<4=f=T@i-K zpp3JUL8|-Vq(2?%C8KL;LT-mQ>sw{)u*|A(9`<(`VtB>A-+vz<+D7Y`gL^ESa}*|T zyYhQG;e-Wr!U@IOr(Cf6{;=j}vX9Zbv(MMF%vuCZBcda9gQea+c|{8Cx{M5Cx1Kam zTr_nhzO|+IsHI;8Gk3+Ri_T;f&I51uYCZJN4%ML_HiYB5MQzXT!nAYVi>7=S(%AiU zW$7-r!mI8{Lb^~FVs7xJFfk#KG%%O_p2G0|@N|d-27LN5+E(NuDcF7x+81c2+y!R8_yM`-*WYn6sjGv%Wy&X)GmDJ1unt@Kf z8&EqwGx9x>zM96|1J4;XzH=f_pq z+o>s6n}GrU^p|eE0j)kYwjYJ&1CiIM#@EspYw|PsR9KlCjN&G7paMpU!m`X zRydv_;sgxZ^h6NX!$_y1DIoDXox#*l@RTL;h#0_jfci@0X+$jhJV#0^wJ~l)g=8iws=X~WisCm#(3~RG;o%Bs zm!f0@2$!e_r!_c5_z@>85e1OCBm!U&7@A=1LuY%6z^i~IrnpoI(zrm9N92&7t&_cQ z$W1vK5CQ;q638RmkabD-?D{x(U33qvqU z6G}u?pQLk&#?%MH>XFvgY(m;#WOC~E92(h$I#h_tQqW?^NrOS*SSV4gqQ?ph^++9D z;)6i$q=v3*naer~NXKplL#RnWAs+ZOaF>;D8JZozpQh5E;@ICPpofq31|bZ?xbT@( z#0wJ8#C!&Ux?gmC#%@b07!!RSoY|Maw}^w%N$cq|>&bZ2EaSrYi9vVyv#Pw(HWkBj zQ*=^V<2I$(R!7p@X|tWIX}&53eTUJW;ldwH>z_lj$P{SsQ*~79vWb--sMW}MMF!J$ zK#H5)t3^)_yxp6GGAU&hz*Ay(GIE9V=2~(;jwzC)2k&S9oFFp^BL;iOU5&QZJ}UvQN`Zww84ST2L@7-nqK;Uv%OP z7J_j_w@V@m$UhVYr#gvS7MC;AfIvKF1cZbjFi8Azy3hE}>7MexdJXAi0{#Qp*=%qa z(_bCQUhU1)1g3k#{7<2K1lz{~JvfY?mHu$3;WDJHn+HRfaq?N z`X7s>@I?VKBCSgqQT%uuRM0R#}Xun#T zyZL%wzS#%QM*j6?FAbdz*`EIMW{=Aa0|iS1Z}zjmo4vQv?Z4jawVXqMH~YZLH+$e$ zjYjpl-ap^$XD{FE+5h=w&nke;mJTQ4v33Y4nzq&t&EY{`%o2gHAa0V)0!O2EfYuoV zXr1&Vi&{f^qTY>Shjv>C0Qb|><&;j_dTWl54!@4H?_;39lH{UHmpffHS6R%aIQA|N zBKm^EJE_Rl+vU-b1-el`>7rW1MMp-NrjFQ<#IMq5QJtkSZI9n1>)hmr&jT~skJ*h> z2fOCAyuS6+>ZhxA(}}5~X`9WH8SOqsUFr=VTAhMyR_w+D=Jxf0(tA7NAKbpxIX?#3 z5Rd3c$sgdcc6b_h!gf5Cp;G-gfo?($;@*H;%in^Y(Bv`Qdh{;D`_>}}$4H-F;O|^q z_yOa-fjtSmEYE;t+4px)8jb5m?W}f6(!+1{JRR-H&cERh>|u?5g+f;ie8&%FTu*xD ztgba#fF~&0%H-YO9$lGzRJZ&}?Po#xZB4eob_qOzOyiy(F`Fl^Y0I>^z3vm%m%#+M zs#{!=7DAW@ot7#iUhBTS5St45nsv~r$@*okFo8RoIimX`t(ABe$3|1u3#!c=RWLJZ@Q2y&uuV14Uh*mQ0?A24O6Q%DpoM0SrpWf&_(PA8Z7wN@P$PM zHgGLJ{@7vR^x4f}0eo#+{tLU1(=%Yie?uY`Q)w5-k$HXIkoehC4c892R`og}Zfb9_ zM}!~TLGQu|g0Qaf`-vcu+5#8Ylyqbi%%pe=I*=~4Rwbb~zMNb@&!5xdr9$;(?rXw` zVz8@TJW7PANM;iQvKo){c&*z`wWID3n`9>aaG;b*uw_Y8O8nb6Yl1AcfZ|RH%0rZg zq@wu&R@`a9tf6_R$U;m8^X!X$tL&+GAwxP}0imauzN$#-yN$Ae#h_c&AMz2N{UO1h0 z_x-GJ!n2jlpcx(IXUS>{YenHRw8N{h0vT4-RSxhz?PeY`?zH=YVQfiZ!dvY#yJ*e0rByulJ!*2Dl(`Ozs)^)e^?lB4(T6N z7S1Hv6g^Yzm(R_;c}8~CcVRS=s{PJ4c9Ln2 z&ORT{jly|@B>CSWGYN|t6(o$j>O{q9VPqRPS*1zwGLa0d6N7L%xEH$Hjm;Vk=H@=A zgLW#-`ma>podh+IU3lJ4Xt97$CN=n0%e+owO{{qpX=xOpoSPNZE{NYlcZBGk&5OGV zstVh?DYE#2pQGkp?EPK!mSRR3+b@+9KSd4uAM-<&zZPl?VvGoL-!wk3ymwaVC$X7E zbDzjXn(9nUD%#Jw;xODKev`thuiIp>ct~>BW?!@AF$I^FRsEX7d;kz1e1j)fUr*>; z%phk=c;PV~XZ$rlonLg(+3w{2HA?TS;}0AK$;qzs{s(dAw8@x<79E|Gb!rcXuB2~# zs~A<*yXJSc_?}3%i(A0h(ksET!c?<+d>J5edRGXpD}Xu-^F5kb-kTidReKwL4F5Sl zslLVEZp9I3Gek~(?8MNG@7v^`B#Jq?7x7o{cXb8%Mxo;*GYA?{{Jt0%w&*#~23lgP zvvIWzu8cEqVmH)pO`AS&@S%D?Z5C-BPw7_5-0 zDy+%D)e6G|XT*uV2A)U^n4Zx{D@&TfnbW?rEpxv)ei^*lMP~8%Okdv|YQLBQue%tN zbP7V%8EgiVX!hF>Z55o|11+sHO#~W#uxDnocu$7^eCcG@-(25ThH;)q7S@taYUa&q zAK4$dg$Q&VHJcIvMXOp7W2TAiKCJ-2lH{Jr+}!f8It10G?$BgYpt1onh7iAv>q;@!!UBjG^R1bv=%jI8~?vgCc4@btm zzLBir9F>(k0G8M{Um$bqlq^{e3+uRzR4Sf^Gv6iYgO!DsIbAbXl74?D7<3$9##}7c&z!s)+Tr2=?g+##7la_AGm)QdwR2C z(WJ1`Y(gW_`>HblB5gleA_Cz4oBxFSpHdor4OeCOXwvP$XbmuMZciuWh0!%bsxYLK z$|@LoDG~zL-zdxv9QmLjLi&AuF!U2$s<&K#TBP3RrA1QAVdqQL(|FKbb_)eh4*F1o zVSBSt%$2d}gX_huLWno=M2OXEfJZ1e;$xF+4|khB)b_#keTxqD9>62iX3Ytju`${n zI6SdSV=c;j-}B@)ueLOu$5ubr`TQ42xNnBu3sn8HimJ z!gB*P(fqrY7>EO_{j3i#&$>4DUNv%CswpD=v@`BtgdMdC^i%MXVjy1IQ8P41R7>2W zzBsZj1n*1~H3Uhk2q%HWLu`baQexPJFVn!3a3oI`-{Oc9>aL3`1|-^*K#>dD*NSZK za6u}dWJkF{y-o^fRDL0ddmhDmitr)^hIgfYw?tlm@25#JMJI}k${OvUKrPgET}fuZ zqJZ#B?L%4bFr>C7*+W8|(Vk6Mh?Ziqk?SSj?^U0Kzn0{D8s)0y?=A#{gX!cUiKdDv z$iid>ZGT|yjhRp3KT1)9Mw(ra1cM7Bg>WbtpQJP!`V5l9w}LSS-y`stL6LCOORYp$ zNGh&Aao_S1@QK(-ZGMYxvP`vdON&FN>7zNVhtqt0VD!mp`8aetj;08g=Dr=$gG+t_ zCAu+>jv~qE^Pw4lrw{qKGa!6N=Mm2!>48wx+;+6JCha^r?V)#uhe@Wje6TN^jiDu@ z5{)kCigpXr>eQk8Xib$0P6V0g$g5@IrI6w)1XJ%&?RRC3=O8}Y$UKzImN(5t2~pm_ zWdre@Ur-wBZ&5f*_HIiCI2b{sl%Ac7$>gW4_0U6GhmrPSPypXArAK=fI0wy%6^e<; zhs>-ZlcbSL7dRH~1s!7b-0Er=6EYVS!FD2;(?b#(KI(Qhs^e3byJ^Ci=H7W4*gs+>JciUibN7$L2%CDv5EL?Du}tcP^bv&u^T;o9{;|5Qh%x^c zJ`O}SMJWroT}&QJA1;#LIP{DGZkyof>p+`|iucWW4`b8xGm zu^}}JO$y4hrEeTVHnCVWD|KTG zOpi+4wo7rlQV&u~Hj@K*#!AvsY5p|_e2Mqq{&Q8J7yPe=2cv+U|HuKe{$~#O)+OD~ zK7l*&nz^L=O_Q!iKKsRD?sG}^uN(X;-EUoHk&WgMd$d1PAn_O8Q`YELhKD%)%5PWj zPrL`(@IQD@GJyA3MzCk?|AX!atvDQpfI5?CohdOk(ul{bTsj5fx~t96E#E^|C(c@Z z;K=~pe^_uy_jBPxuAM!!(KYrh=@I)3L%i#bE#LC{{^=0pt~9Y#az;X2K)@(=amA1A zljXYr>LpqqWyQHQw@36FlF>rZ^J61R;>PfW=NCzvDY?P(P01V)E53ycpq8~dXQMlr zwN?PkCOlE+AUR7 zWsC93co*T~t@S^~Qil^9o`dY4Ye3%RH30M1H6UN?*e54D=}?B=hdyf4vXDh$fj@=s zJdX`ziPz$i?+~>Mv6T9g1C|1Ez(0GKdy8L%tkt@j2DKndb>gh*%2=fpaK<0QFLS_& zN@gJ4;`z%Q@F9PgNl=$CyqpEd0h25glw9V37xSS-Z)SJYPTz?FIbhO}q{=i^-xSYO z$rpKQ%0J9S8lBCs_iwbQ4hoqR=Wb-F608mQYxRT4)d~icHR!6Y9WiZYO@w|Fk4g*| z2sGdba{=}R{>Y7-AG71WZQmc`Bk(vLdu9W4e>I1$^l-iBV}?g?PKPHi*#NqKu2BNM zy4xtBJrQzPZ2w%i))AolKQIl@lLB=AM?;-Ux<4Z@#oF#^>tkKt?Mu49qc~ZsQatAc zwKdu8r(ygr8#)%<((7Jctuw$n#UOu?!;T_5?@i$~+%E{z5h`n!cp_8QteUOP5$>YI zRcH%pVcaQ;a8L+Xc1d19{tw+h=WLHs7)T zs5c_{M51VW9A^!iGRpD0Fl={OnV-8QrZYz@mtliV>B)Vin8QB~fZ)B%+H zP0qaG?x$2RLZ0_qL1s|Z$z-|Zvm)3`j<(i=U?JZVUaswaa^*D2T)doWy~Ms3R#qRd z7GKiU+P}2jjB3rh>24$pgst`Nq4N2aHctz5Qgj#j8AlDgJZK2YDJTaEI|EY6AY=Lo zrw>`V4YH&NcRJx_cz3B zi!R7OE@{le@3saf2_`}LZKd0?LRzz=Ml9;PCFQy}4v6S0zm3-g-(<(#?=6h$9p_b? z|Jqi|@_IrYB+55R;Vn8GIfYf8<)qIPrX%g2vKTezp2{b?4UaT*onolI=}G~zS$y>X zH=BIJQpD62Fb65lvWUd4^%huSipd5ll?13Q;d`d2*)Zi+I#E+yx0$?qi4``=PBJxQ z=3zt#tYwXlPM{LDX%dT3RT;JJbgR9Ua1!ZdNNQKa!1tW@YAPG+J+;+6%Wki5HT$og zPPE5!AgL{$WW!q1pJ{o0Ksc)WEI?W0$9(R-#Y6hDJ(;*fTU5e{>li62fVgsD`ogb3 z_c>k@-cwK7#sVfjHZ2L68+%rj_sn&E(;6G<;@cxfzumYXLFvtjaE3Sz|C27j`)APj7< zU)x*K^RfuPrc3N+p8n>mQ%%okep3LKAkEq2-&;elbNjGd4fwR#|5mhPO>IQ4s)UrI z5{#KJ0^7HD!ZjY}hq~~v=?Ay`*%~PGz|UVB?#Ao7Ii5Rd4ki8yI#TO)f#_gS7Ma0{ z8zt@uzwigHPd)^opHwRMh{2m%fjP|K8=shtdr4p^>EuebNq6NgLj5Asln10X<7dxa zSTaEi9#J?;Mt66(d~3#iZA2_D(u~De$iVX+dOb~mcWpWDrjA8g9P_>=y51pmr}gQ! z#I3IJ@g@;sn7xK+wifuOM!Pb@OSg7eWeixd8S#>|-=IjYNS*{gtPVIDtVX`-p+aQ; zX7_79A4n|*H%Jz6R3;TGjj25J&x>dM&|!0}1+Sqs^I-oYJN~tSf%B7c^BH$@eCw#7C?f>%7&o;6XeiOo+L|GU;Z}KoePS0 z{rpHb<=sn$9?=)p_ooj-Pm1SEy47tax3g|3gQb~)c5$#rrp?!TOv{nE(-e>xJM(gN zZ}I8K>n8+Z*SD^6CCV0m@_=fT-C3#m0f#JTSy|`q$P1Ia4V1cFbo=_BqXF*I+OYgP ztf|fu38e-Ybob!_Nh@-llm(R0DFn2HAGUbk0sK67*_#43?XOaQjT9v)PW;Zl)Put` z=}>^2jMW~*X8d?s_<@T-cm#e0FUle6IOOg-fh)E_sAvHHziRy}sQRe%MT+Zg8*@x< zmF?+LU9!;A?<#xvG!akrQ5M#m1T3A#a5?$+XIgz>7oTIxf3y^S_;Hy7#^ImSrI!B! z64!XuJTSA}TJ}4>&wno5{(Sr@o@U!S9tGS2wgpJ)TrvJm-;?~&^g2**+IC_vNu<}P zYqu9l5}guRPZxcPGA0RLV~XUz@IfiT1yZ04sW#3FZ=#_oVX9jW{G%x|0*UO3sZl#9 z=qM+!BseJER;`UvB}q*dPGd2>3;|0;q{-pXzeO@67HxP1u2Fy^==sK(w9^WQ+1-M+#A@_+*0+*=JCi zxa72NH~@|Z?QB!yiKJ$kW3c?R&F#je3bZ7e-#`gJU-a*IgA{_?k=i7 z^HPIEMm7}UDOg|%%(&sjl-?ztsdU}l4jFSLtzPuwED2$xZueLchggbe^NQOV{J_K* zs!mk>M z@hzIJr&`()GF_1v_S8w|Ke)t&9Apdd95nwd2yK5V4gOjXuvhSkW^6QO`0bKhkc@(^ zR_bF(DSt#kws=!6SeLZO3QOq)^-EEZd~UHABSfIoVYJ8w%NF3Wom;WlAY}BCg~%e> z`K2asO9-|z%X`~I*jvG7Ai{y=P!@IaNo`UR(M~$JAhO_TQ;)e6 zEci5>&m&o?vVQPmvWK48)mu*dxGJWJAe$4><+=<3JQrnr-vSDY1S$(jqtj#jzqPm0XCBc{_hn@xf&qEDs z<4y4Ouj3NhFaIeDq5woe135zqA%H08k6`rvL5jWKuhvfezeGVWZsLu{FJyWpjWa}E zo&bW;=kG!rCCZiGU(fMa$@!HI`-1d7nI@x+z`07`^|rq@T3Yv?{k3=1YR)Ppa1I$4 z!c>A>MH0&oMzdTL;5eckGdd&^i9wxeFOSlVm&AAHte250aGA*H&Uf5yLwAH0=^47oZ*0fr7a7_5i3f&r(u{{<7ze|lXnEJ5~;}J)C`uu z=C-A~`=3CEVW5ua2a3-DQ4sN`@|P;@Wic#3{MT8i*(5{!F{AatH2I0rSDGRgKrq?_ z2u3Tq8LTt&z%6fSpLsGpJMHzO0gVpxc1=~>{tO64p@pnYI8v?&&bOS{P&h*1yEKg|LtQ+)o_$Fo)xCqb2ccts6{u{6ZPmNS#|P z!5d&qdhvRrpMfe4S%Dx*w3p5&hi0Hj^1eyQs2&!7yA`xqB znU*Yx=2Wj7(J8%j1nEviBoCK`wdCZGu#mG2Tsnf*vwTWCPHq{gAL|| z1Iu^l9MTFoJ*3N;_X^(jwoyLNc>nMO<%MkZz-*;clH;we6j) zQ<;+fu3c#AF$DDVq}*9|mx{Q5Ch_rXsWIcW1n(Y2!Q_++PKLxNDaZ5r1)=bfHI)q{ZN>ukt%6QXucI)+To0sp(HOY?FfUNtQ*0Y|(Mg7G zs|tE*;L1=qu0Iw4Eh%<5(U!ZH)Pl_5bMO)kW$9lfNr5mkp z;91r0=g+4NmG1Ff;LkBQg;&}yTWAy8Yx0ST`Q2n+XbpPwcCYKi^Gn8ob7y|pfNEHd z4hKR&L3_c21W{SFACQ=k9lAw$RM!|A==dG`R!s|i*EG|E)S6_4M+#N5OOt>Wtn;=*RHJX1&AAUEmap@tt-E zTpR#XXks7RkE3O?f<_jV?wU?R9N0kcvmk}b^ds3e)WKB^Lz9&r!`Ce>-(2_P^UA! zv_p=nuNG+8w^T1cKdL#@njs+c9T3}W8AUpEw9>gc0QSAj^?U2NRwf(5cDGh~ZR&LC z()+WjLLvS9x;D{sSjR0@zOsuLcXV8Mi~a`-UCu$4fqKkx=d;XaowU0uSE7fxde}Q} z0NH@)($$Z?r$ZM%-qLeZR+pzKY=Sbslz+bSimm(yO6~mOD{;l|gXf~)wzsEmYx>UB z6XO*|uRK3vMxAKdd2_I)5V}}V>d=iL9g~aPG zoj-~=loW6iIP}P@K+4UtDBw_vkYJTlkIp#=A0)AiCknU;Xxbz?L?mW16J_aysf{M; zs3W;f6HHITb>Oa95lCuWl3hK$!w&KmF>1ROfQOP8f{`>(lsAsScL#}g1WS)_Z4{&l zhNR31B>c8cfrg}f{Tm)avFf;IUeqOb%B9%fL~FaEMRquiI?xvL;ld3BvSYkR<4*@(M4AUO_K!@0?BDRZ&O3N67%P^12>`>Lek5+;5AU9_8pHs zSR&y3;UGzE>Pq0BPp=Ns6{Nj%{&4RZYg@D+1 zz4zra#dcV7J?aejebZ9r(eHL5TY!9kE!CMK$-=kXEl6Im7ZkrQ2Z#s|TL%*%!_Fcw ze8AsX*uAjJ?@o$2QEL2rm$lw*+OO$+lx7}pcpkkp7Azl(?~28<$qe#DG8KRvQhk_! z*e^pI-e{bAx9@InP8qTwe%9DDk|8uT9^8^wL72^iE*zRq(Vp`be}qGfS#DyfqbqR66}ZJan^5f6l@u-@;TP0=>CINsJ1CYV{;oew=Kl4r5Yl`Fp0O$R$R+ zFYN+!Uqb(*T_CUZ|7;gvqQ15K_#f>8Jq%+1Xcthr`Rv$WfPCsn=i!{o_hS`KkOc7( z@*3C0+G_5q`}WIlp_Lv8=bv@~@2Fq<5eaL5w+r;|^?ZGWNIOe0vlYx#zSc(*-vbiBL`FW0VTVVTG*LC0E-X8w0-%Xbyo}L- zN?%G+VR!3!T|HBW$TMy)fZcV^|0IC108M1^CjoqNNfSx^p@|SR85*3Hm!)Q!tjTVv zT3*^_W-Ppy?E;`e&{WDM&eO`02l`jLK+Z<3>o6g=P`JZvH>7|q08^J&b+oW;F~!5g z5aW7TYUWeG0Lou{M2IM5v$0*qa_iZx_@wt-M2b`zh-?{~B(0J$>fT+^+*LdMB}&sk z%rmN0onz;l;)T)sk*B8qV_^5bmmA|jldG2Oj!8xFpA&&bfEEcaIS4nQ>^@Vi3QnoP z%pO}XIUY#lN!0&cF@Rr_XSDa>bA9*0+Xr~Olb+d+VZTnwbQRYjUQe%0ciB5WKWh9u z+;}Dy6uC($F8Pm&fp2B8v_Qqc5G!j0P%+@@Ju}P}P4NKj6m?yu+a^}Q8mJhsT7d7p zAp4?CGC3hK`D2FXYyEl}`2!!-&+p8q)+&DKM|{hyJDF)3`}HQ=1jqaH87x5B~?A zcS~^oH=;S<@sBC>gQQk6XAHalU%CKQa@N0e0kMuNYWaWZ0xRLfMHwj!4Te376?pUn z1qq8$;><^^wRRoX6FtAEWP$V%i4tZ@>xxBo5k=eZ?VgY8A@nzrOvl$WGp)Z5hi_xXvyC!Q2`rCQV3l1QwWnUwN{Lq)(dW zW;SEep1UzPDoc*IQxGupE5*hG+*!@JItLc7%|uKh*|rd_~nJKcA8zpnY!C$J-J zoU;grRJpt{)^PO-#v$Rc-9;TXJ1-V33XeWhUqT*XI&)V?x)9C>) z1-24VvkinS$2&~Ql&v|ZH8!lVDyi0nLs8Qz?C1p5{CCNscVMz;9!wV1v@*{|*(X!} z%+;3|w`*yzlYfD_)mU-!Vf@$-^AL;{X`Pp$wm;_vh{BwOGSzqp#N%ow!Zq7Uuo-aQ!;PNk*zKYY)T5;sxEJEr6w0ZCndRB@;)C#a z^WI0y2=sF$78bQ}rlAd}ILMxNG2< zf`jQkPsrjKb?f9VxL1;rMblWYlAvhyse{;zLL^?UkMh^5s)cNuy-80UbqU@j{cIO_ zvUl^morWE*>w1$g$h42XYMkd4K%DU^fL`Pcm588kzerMOASf| zr-0=?N~4UwZTQ|30jX%Xp@Sx^>%S?~wHs$vI zw?mRY8_}cI6&}{Jw2tiwSz6VZ()Ae+LfN4xi|Jh)>F&npFy(wfdX24%)arV@f!mWr z2hwkqQ+ckA>TVG1L(Wc3Q^r@P}(w+`UTYvboIE*Ie zl`HSI8%o$SD45)wQCv$KQ}?TaO=!;2fMpS>+fkoGWLqgZwdYu`K;6UFTC?tA&-R#o z81N|q(!9J+`<_&fu$lhM0R#|H|kS=d(#=4 z&*SM}Z(2;ZUzt7eIU|Lv=Wf;Km0D34CgBrWE+fAYrht=vZ&>kzLdg?Z_s9r{)V>rI z?!+KN7-nWUJ-M7@x9_}x3A`=!0a4{Vnqy=Ofyw$sZBJz6#<%*rRUd6-UKg5`jOqDf z0j+V-ksGz>l}9$fECOAEVQ0YNpMjqb!fsjpzgxbN>vR$6f6Mj!{^0~j#rFMhKPDr` zh$E2d_X?8*$%NjGpp-|?Vr4To>%HwHk4GxB&3J+H$HVV39`|ns$|Aj+LJZJpFk!A* zf*+1w9T{kaiG;l3{*<|+HJoC!fR^%Wm*@56>z6Z(B@cpgQBr3zFMDo9Mjs_Y}c6Ks1xV;l;k60$-g=*C0KNFqo;gxG8ZpK%2E zvhOs?_pU4=_=1}6AmTTBq^9BXl<;t|1Nxl1d7nsL35XzPWF!@KL6y%v>L};5Fmh;w zlCke2T&sf7FwCncZ77AVM7W(%1Xu>f8;Bww2*b*aFoRNCNQC2wBUr_KwZCGx@eAZq`7kQQL+xIG&A zS{|*WCM-rG9_LEQ_B(=hE^zORnhY0+u*DGUNB}uz+wAVA)shU3q&H2$&bZ-kq7r#Z z6OA~CNDmSLAZf0~17prMG8S(pm$-x)SRG43t^|J?_s0|TL-+ObjfHIc`-4yXEwJRl zjs#3JE4=;0noPubC-vTCye}*z9tMGltJTMl-1_^zM$^DVCI1$KWK=^R`}u=7fS1aN zu<*!LCWN{RGzI1NizC`-RGPNS-Y9R4uH zHH19I2?Y?kc2qWaXV&+rfk83EqaP_>t5fGG!4X5=T(Pu=PP+UmBr3Ju*mIdzor#|9 zVfVzcwzRVbW1b5{2VW^CgO@y{me~pgwLxU6lxBYw&!~qd6G&vuQ@g%CH)R*i@KZ@P z&&qjHOBw70<-^mnTXc1-C5?~_iNZ6AaSFH6&N8HNSM@bN{YmFH;rNCTWr3i};)3SH zp-|7f@=>Ihv7sVdUZp6X3Y3e6kygodE^Jlr#j}*o|FQFPM-%J&-|qd?tEFlx594Vp!$`D)IC8ufkg()ClJSI4WnYc}0*_vjl)fv27bF=^=#}>t%MHG*PnJyJc+P)(h8^maYg4N&@N1gKjK{D>8WS{;|HJHb=7GO_5J^0B6R)f(A zl%_hGbX%u3M}CY+oSOov97lVO*+XdqXsmzN{;18943+rh5y|;A+q^)#uYldO>|i*R z!-n_A_a)qtxYVcq>2wy)9m)8;forv|GDtGE{+wtyufH)X{4>js);#Rf>$q0psZNgz zz)5oRmh$8pH#P^8N!cPLwR8Jp;+AL!i|3E?hKad&4(QF#cfZe&APKfAU#^1Qb2s~g0*`*rXEb!=G(Wm{FWNc{tj5*=<4>lO(QXk(#Ieiv0fx=h73PE}n>%J=C8iIieAv6jO zetzd-a|*-8UxUTrDHa=xt_~CAvt!BG`MIN6?qi!+ce2H0mE9`S+W0uEP4U3q^HcLyUJo?Xkims78iRP+jmyfcG=As=~!KWi&ShfvqvCc(?S_S>@evdtF(m!#KoyupUC0N zu8t8KNi(>tVG`rc?>UbSE&1ks7y1BHnxV5=pyfmq=&)%EzK-CYPLEBbrZpEf?eYl|;ndyFb)M%3nz!vPLHdv1 zMXH@>aQBp-V#u=#tTU-c8qeoq%G-+?UeVik5PAK%V*@b11=#?FAR9oMN9e87&l;;# z6-9n4!&@~|%BT4sp6-daUaOccfs3CI3jPwO8HWos&0|8~(H7S`f3b?9g({4lt-zK!+ZT$qIyI52yVhO$}A@i zjYF0!DZ}hhJbKOOBNbaIy(~+Z`s?c&k-^CY1a?WbTVu8EJLmc~=8Q&cJZCiuES+ro zmoK=wkF)$MW}FPuo@!CxT9Ogywo8##DoY(&QIxF!P$lN9#%leYr;E|hCCyqkBG*Ga z-8Z+^2Q}rQP-?i#LIAV2N=<*AhwzfgeBDpgiTFnJSv!)JwQQL(gF^#w&KU!w0Q7Iv zn{JjBl~l!aJxqJpqfZCeaW!F9ZT?Vm4#I{>FIF|ps`wOVYd^`~CJ%*)+$kT6=6+i9EoM(x!AlztZ z8yeh7{hEY#k%E7GHF-w?AeAeC;4G?48E2YdnbwlNTo|W%*1|&3w^=1(e9K^kym-88 zy2nMZJ84Wj5ZyVwQKCr}ZdEkCClRqLq-KaVMNyVV)NRfxXgn%a}1@W9aauf+nc8(M<7N6Xrh8CXF9|LE`Q+SRI#p|LuVJTo-K)2wMTmdADUK+jgV{@d)+HrA+Lot*N4}Iuc{ip z6ACbwbAneM{yE`Mh*`769mqy&(tZ8Qmt&XhQ^`wbJ+J4m$_P=vy0`WiPI{;}bdlon zU!Hp;e54!xJ5$%s8}B-pXV4$YBhg4CG95wxSPwt z$GAtm@mJ5JUtg07T&L!n(Ox}x`a2XO=-bq5L_LW&Q*7u}EPN$AIQSe~Lkk1s!Z0Q7 zp8vn^hvGZRZh+7KXLry4DwU7mJ2} zCCVxN?)hJvI@(4&I*SUs5e{QVM$e)}@N`9*Il}dFts2E5=!|3Rsc9W+BK*c8zbd)m zF~*P!M9||#`S{0(7+auw`Q_$Vb+SXi+Q7yl-_d+ksMq1&i3O{jn%&_l5Qj6^QjS^ae;%}WXy1vY{%q7%LFt? zP@-UpI(5`f++=(!|HV}Q{7T3*5-z6f@n$onlQI#F3tqVoO=Tj&&P~NVprlwyO@Tq& zmSKjzBouM*!E=XO>V$J_Z;bP_8ryqI~DUbCs-#Q+$={cmn*M^5;(NX zEB!AifPGgVrUa$H`2Qvanzr6}Kv*vFpmU}FKif#33?T-m|M$V^f7bi`DJC51nZ!C6g~Tb}F`GEyrlL2Srx#OA}kP&h(@eEyb~*kA^<75KNtIouD}mB9ks zF=%VH!k;(CY?#*ee=m`9(fLOYoMi^%-{}D&cVkA&ixsK@Fa|_Yt}LQC8tpP8!BQZ@ zHM&RW#kYo5o=8__K*=xp(M~y;ljH!50XepVt3j}TVn8e(z@EU_zcHX(X(5%ojOeon zGH1qY1H*ip(h)W)t~XaHovr4#SSyyd9wM-00%`;whdYx!MdQqkJ z=sjox(DP{56twX3ONJ+DIl8Ix zb#WfnGUz!}UKltJFI=#y>x%;Ls}o3)=s&=h`7_eS9*oX>Xcx4eLY!m;Z&b3jjI$Nj zZ==}i`@ZPyZbUQrpx(ln1I2e5if1Zs=mi*zTl3s|_Tk2DvxF1&AE#a;#~uXqDw(al z_wjNNT{2#8Ia$Ixj$B%{y#5=Pt@8V zY<69-qMjuDvFX9PpWF5w-XyV;xct@^N8z!7_@0%`D2la}!E0TH(&wfsWKD-K>;Q%- zCv{lAvk+eRr16V{Jc5iB?&kRIa@D5_z&EB@-YFFd3_2EG=@BPpGWDFxBlb*# zErm!WwL)!GHdbkJRT~Nx;_=&)l5C8kSvIbxD(h?eFZF#rT!di-M+Y5);SV{W@bTPa zsi(Q5=ljTKhdKsdblFlB1!6MPjPEu<#j02w@r03d8xk~ZhcyiT(>s=8JBsKL%{~mK z*uW-SW`5$Odxu=1)cf$hT^if8W0eVJj)`$R1W7=s{qR==!vzvR zx6US;t9kEtlQNDD$QWLkwzp?*dq74sj2d;t5lUev7o!|TE&7+jD)8h-u?X)N!(t#~ z7y&Ydzr&zntz5UPaT@FtLk+8Z!3a&=7v2SL*I0$IB4(UVKvf_|!QU{UnYO`Igw|9o zbB=fyb0S>y1fA@WR-~YG5UgbJs!Dz&PP^@48>%AcK$(SmF5KA7pU>1lsfp{I{;XcP zEK#kDx~lF&(%te}YEA{BHC0+cvcfkKN9t+1G{7J7GTVt-lFGG(`Wq3T6Sr2_|41P& zYmyO4p`<#9c$)JjGhK%lSGSj}q0U^CO>(hTRW_de$gZ_P;jIGz=UUEq<(tmWQ1HBv z#;8p*O9vjYuijm~oN|_>CZGOLtQE;zj~~^Pyy2j~S|^qxWXR-0BxlE7w(4px+QQrY zuu>#2Z}s-*TSdi2t{xRl%*Q&Gx)(Czra9-VOZKp;`|I2awo@Ey+$Cm|DlYB_yS0zp z2M?@LtJSdr7lXNL1tZk)bY(E<_sZbKX#Ov%On4xUG7o#Y?6`f!oi>iSL4@$Q2YT3= zS<%cGj})qYY^KKu>^^-fL7MQ zV+}zqqo6dLsazE+T;*hN2$Y+^cFg$SA<%oFS0aS;7s}O7KTN_gC-QZ@AE5{>=A?vg z-;id5Qoz-Y2ZwP=nsPj*_s@<$pC_LI4WAcRi)3=ivp#IY0iUD;+u?{wZ0T1`g)bBL zd3|!<@o7dI;-s(j#a~T7*ciH*=0sp}Sl-?uAA9DZV z@Lyxi&l5D3joXW4gT1sA1C0$lrdFT5Y7K5r+?z1YCq&!)X8M*W>=drwBrWd&%orW) zz$rE&vbcJy1394!CQH=VtNnP}cFPyvyKX)osPWBMCVet&bIJPJ3yKtOzrbybTNOEU zdhW!{SJ69%A32Ss^HSUDd~3BvbB1=zQZZK~(Kzpl0P-pp5lgcK$%r1AklllQ>L74w~}^%CAoc?TF8kR{k7f@qT{qTVzK^&ic-1tVb@){l5jm zN^Y_WX+>$D>xu46@=s-2Se8pl9ucKhs%oG#+Txey$@3c!2*$!UWeQcmtD72lT=)$S zjbodHHmq=eRn%BZu0D`3tXHoHeNRqJ^4gto?m@gtb*5b!f>Mkh_1r!A^q0QL&B`WL!$x)s>30U801Z16u1!_Q6bl&xMZMtkQ%|A zD~p$Ek+AICpXDti5qXFKT-!y8clqN1p&(e8sK)y-6m6{fp`w2{XdY(TidkH^Buof`uY)lp7 zwsKz-H%gl`79JbJu;eU(8yV0Q+dmikxXWM1(PQZr8^Ml@6f}-T9^8+=ibQYrZ(O$O zsB&P3qBYw4xf;g>WpJy4)N*!$W|mp zdrg!v4j`k1=4c#iyBV2)jD2;Lph1%8qf9^I?=;pG)`y!=evnAF6+9)POk|Z*wGuEq z4u*=Hu47_`K{l9UWYbFGT5eGDQ&oETuss2q$GAYEEye=UBRAFKdMWHnQ}R(R0}f}x z8Yg6GSDjBj#h-&n7MTK+q%1%oomKJwvcZ-wsj(2euX9r`Y9OyL;o)Nt!Z<&LWsf(I zv<|~$axTAKag_`vBKq;P`_xo!x47wRCCVQfmqurKE` z;y2BHUy$mq6{(o=={rA2R7l zAEMo5>>#F{;hd7V!tMU)oi?h*E;1c~P~UXgn#{T-Vy9ZMV5;p0q>1MOTiVIK4hAc%dS8}N ze+`L>5xMR{c_I55FDQ&q*)X2)JldMPgOR)^)Y!p?IaloYDtj5jBq&vO!fur~ouT~H z-Tc>h1-KkJ*wv)q+N?kIb;dZtcS;4tC~UqZnOi#wJuJ!p@?T=%pRFMXC>GxTuVSHe zDC!fl>aJq*_Rw8P;2*J&g2AQY!1{$fnwoZG4BQ* z1OCisjQ~ksbhAltNin(@`sovtxb4rjzx-7+ zqu2Ck=?tClLGmN`>Oe$3&aLBA_~q7|vcx#6F{z zc+nQ_^ZgDb3Ij47(~k+C7?vncCw0;|6)+jz$N9adv>8s%yprXzy4b#^MuPv|Fknxz zRUXjU7%SleuD)5uijdlF1i!g%O=J)bur;$Y9RQJGL#wUZrZeO?8kCAnXJkgs1;F2y*r*TCb?=nEG}r@{kUNSPn|&5#42pw}d!A z9&n=kIp1puNvi_i1s#N((u#dml3%q9RN+cWpRwu4>+GD7>}#dI$rQfD&m{JS2@1Ke z2H5<4&~7*Pv8~<3tKth^uw2cZSMKLFxm>N#1P3lHmX zs#d@ou6SJii`&6y{TIta#gzLab*lgDjLrmf6}JIRPL0Cc2<}WTTd~8&K<7inPeS%- zfuMsh06GY!&b5`YxV^u$J1)5gtj&MUx{PV>)r#zX@dp{ILu@}kpx z=)~HV0jF#4hnn5qkIrUc1mY2c4^yOXu^)GqsnFz6OAY%ZZ*PJi4#H{WgFTtIoX1P4 z;w1_|rkGn~5C%Kt?memd%`~qlT(OD}x)m}HJ=8I4H+;0bxUppB=cd+bDcq1^Vw-c@ z2yvrG&(4oJti1d=wk1i4Vu;K#?c`0xneCKY5=>0_NZ6lfY)!lL;p3LH1rbf>CHzcc zH}#kSj-#YpDgN2s&#s7-?0)#V3{B+CX~?=6Vb~!IGfe8}CFmd&DfIJ6%7-X$1v0(20dZ`Ch^D&7K?0?GoKj%)j`ss(U>H%4p~Xy$r^Nlf^e&2`2l z4PFNm{zzD9j&Ey$5ja#}pm-+uVUnznGeRDoq~)RDL?J7i+qOisr~kBNsPtAUrg=MY zn%LE96F+?ZP3E{p2-@?ks{y#eL^q!YBR#H9j4e*``GG==q)uqIaoz(nHhyDT6qbv> zWXzp~fV7c9jtWGM>m+Ack*2H-j>%GD2UzPf)1c;G+Bv3#4D}X&bRE325D;&Lku0m_ zq{=22Y5OGQTiDn2FV5!p2MEmNkH)03P3P14Y9Rq-hDETmv z99^$)=V7&E7JDWP-?nh^0Gu5y;WoGYR=CWXTXaAZ7WCPt_?Ij4@u5nE;9Fr)y4E2m zkx5dx+(H(C2GXS9dR9*rRzco)AlCtZMAN~|vew|h{pE13H2eL1ZbdFCJfV4g>b9z} z#M&gxooQeE$XW@FNjpI9eO%rM_>@?u-K+W@_)u0cgIfpTS!#?BF`(uRc2alXo>4Pj zY?OFQCeg8GkahLFnvv!(FQ#1A?FB{cA3{0)^P_k5lUW(C=+9&zTNzQhC_RL-C@s=hzGzOb-E?0Ah+KF(r?pxV`e8F8DYb`WT$ zDcRX0`b9rFHhz=9LUgFEGL4A(={7MA!OooIt)niFnesGKWli@_FqHS1(3 zlCN>%=sSQKpd95e#z9|y{mOXZW_Q3hW99uC7tnRR@gl<&g8emJk{&~{tt^cJVDF?E zc|lw!_IBMSct$%uYt+f>>2!(1T2@sZ2se>qS?Dh%(Rr&Rws-00K^N|k;%dCQb$FmyiapprBx+- z_$+MBW%^vzSAf7|i;Ewu8Ekr&(FH^1wbc}qW#BEvfenjGlFA<^b))WoJB{nIhnmc2TK z2Sy@THdgYGxdkdp3)f<|j^C%4>Hp$Xt|ou{qb}!YXYoVu*M-9K?3|d!*#?BD{P?e6 z@=#(g9l~_Iwq`MMW zV-XCGsS)0~3n(GuIT4BDK~{3EFe79dl;s&T2Id%-HHPF+ay5lU7hT2SkjC4L2l(Q8 zT~G$9jz=5h#x@+VzL1DP9}IZsXFbCX$*+mt^o{XJOVDab07gAPi4oxlQy&d_2{r9J z2pwNxnmmZPnzNtDjmub$A-7DZ_fJYlOQM#5u`8h^=7Qm*n3v;mJJ4iLtK|K0Tk-+t zghw@ zlbBY6U+WWvTxWm_MZR2VPmwu_GyrrW2j9ya7uy>%-0$&tW;j=_6ADnRN}5>;)@aX^ zT}i9^k-J14p(3u5$(6136Oy|M!yZIIYtkaxquJT>w&e0=md!blQNlHO7ARuVZta)X zP!c=Tg3w?i=^NAwSOXqcDho5 zFpV=BP?Y*i1`X~1?wR6)8e{YSqcLK!U#k?1*Ow_G|65})5@=R{!=|93z(>QqGbC~Z zY)CVeTiN-;IkX}$I(4hS(bC9QFy%H*i2}*P(_OB%+J$OuJWAdGGN+kJnR4fi$sarV zWqq52YIQKDQXqQ1<*p4`o6Xf`mY;lv0OcaQL5&Q+Q9+XR7EX0F z%Xds|Zv9Y}Y%vFNd9go_XAhAKgCQl_zhFpdtcIqQsL8Lzt{IKb2Ak2?#-X$1ZsC+p zF!udG=Mzev?3UL6aHZOz*UR!8@Q}|KEfnnnFS@<{7^;D;^S!or#JB8(G6T_TJUtzI?t8)3MH1}ycW2WUH{g2#qNwmE z%KE@dfCA`asM(Aq2%(_!^XnGN48`alxgP+s3)JCCgQi5sK8G^p^;bl-T_L6 zy~aQlr3(jz2ICr=OM;lH1BkGxd|)DVIy_a#jdgpr=kJRKIl#6HaIjA(?HQxB3&{&$ zupMPEKsFmyes|U?2Zcr}`rCk6AJZ^=XB0f~r&En0-uH^f_4t7-&p-XLaaGJ<$2$I3 zXv|A}FK7q)Y8!=l;#Bp$9iDLUA$PZPmW3Qk^Fg684GIkl_-dsr;nXkf&fnZ;+vYzv zU6geW8f`1mJa2xNrVjszE_j1mtxh*|*0XOud^WF0jnjMjgTVd(?W$QgFs@Raw zuXAx21C1RvsAv7c_eEDM*GW%TAjh{uORJ7r*COs!SOav?C(Rs}e78gnei5Q(;|0VW38zp-1^L%{$LTWg#(k}Lb z$k$M`EN1QzEsmGVr`%MT?RKM;tz)Rr(@|oWBSYwkoY>kNw$|q6run#-47D$gn)GiCor^uWD@AQta5fW*4TDd1 zqn4RIYWez?VW#nxO_WB4na-`DFRL^sw=KQG%*4qiCGIP29zlJTjT56LBb0}$blZoM zE2TH#kH(;IU^V3_rW6I&m$)SoUBjO(l^IR~vH6kzcoR}p7)}sjB*Q5Z#qqa>A&hW$ zpLI)&LXsrOlxbNA2opbRcMlD2RXhP#j1E-ZF=ht6Q{|kPP^}wFba-0fyMhiKAb;nN zHDPgLJg=g9^ZChfEp5O&8dPT{IuoXj!-h6QptMbtg|5Q}jgp_XHr&ZAex4{Ngju4w z)STThOl$=_8w1*O8Tw2o_|K_ir5c1-YjLY3WWG(@HgEq1EW?Ja)7l^j0aN;|BM z1(=Q`c&rKA1+O^(0KRrOb{iAc#(vs#h1OEgG%=T(qv%6?ojB_#UJ8nFQQ^G#BySj_ zxlIv~O;(!cg)qepE0?a3^S#_2@Ru9pQzfJN6{pUMSP0F0JKhNPUyYD z{U0^f8qR=wv#ta6B9ex{NWOwQ5oIo1ZN!VKxv;A8Vy3-12pz|Gq$jloK^<~**fx^e zs@ZtP>Bt*>o95yxIa& z=jRhT(VDVHhUpe|#U}gqeYL^u(@o5#y~1UBsKid-{59+6KjI9r%WsHSO@X%gD!*|wvfct;FnV#Rk8#te@E)x-=|G}uU#6C1B`}C znFV!kyKTb@x(0T$Qi$k9Y$$Pn(L3egtR8bR&N5c;;h`sis{Ho2X!Em40kuc;+$^yY zw|$sJ4dFXvF`leflbF}BiS5%4cRQ%!F=v5(CmSNaYwExEPgO$bKAg3z#&LeGh&OWG z57jq$=TC`S{F@%2#h@LV%i{Ck^3Q2d&*`CLGE=^P`Z<_;bJ2~RGqVtnna+`BH234T zs=uZ?S__7)O3^O`RR6qdQSGYk-^)lbD%2$gQM|f~h3LuB$15Mlv8^Ot77htQ)IIXn z(KauN$u{@+m5nFJ`3{L19i444*&mw!%a z5_*@zM<2R!aecPQp!pa?bE=~lAatW@SP=6I=aoGD%xYBD1p7}OGpZNFt2gyX@*dttN|_)@@s+cw)_dvi2d% z?WarG>5Z@5QZaX>(CqJwj&n}_5Ue8q>RrL-QzYH|-4!l-Qso@amr?Amb~8rjKKk8- zqDl_!m47o<==k^F|F}!V%dSMv59<+^tr7~Z5f*+>`8IY48*9!Rcyx;h2X6jrC-qGN z)bs1~p1khMUsbbz*Kk z)U@?v=3l&So*%`If$r}6;m414$)j@+yp|iGX`3@KoRK$+4!2l!C z23m-ffIpgqjv@&ZzDs_g9K5)!iHG$0(-}BuL_A-@6JQ^7yhqkW4rMri1h#2DbbLl= z<${m&x#9?5t>GCX0V3r>gg8}293uy*g76rL%Bv&MfUvR4NV%>D_x&OjC2%EccsN&h z)j4(W!e|_0L+59sBN?Mdb_aP;=CJwLviYDHG<#MbWFJ+J)HPUX}GRhdae47LJEkzZ6%D=H5O&27F{J?lR@JZA~!+$L^5dJG7Z#wP*f(Sp!=m`=3!U{ns!8{d=|Y$lk_Iw^JZOW6`W@OkxUC} zubiP+dTOd{l51}VaY*=tN_lL~o+UlFk|bRl2g}St-^zW8V|kwmwKouHYmX9qmV8~4 ziH{rHfXa>xLzE+;D`|47ui>e+5W{_cY{390WKQI)-g0${iCD_ks2x71fnQvV63z3n z?$mHxdlWe^fHH;%7J$DB-buMJ^qqlIPBw2RTtr8`ezQjJtY(p96SE_t*Pf|RQxrV5 zD)2tYi^Ix}2F(!0j3a78G9}oft0GAwqVw*2NB!c|EaMP1*f1XHueg{$lFrF1Ni)|4 z{K_SIb|qeprQVb|hXW;RJ0-P;W{qs6TX>{Q@i7yJg*VqoI_Dye3=96X=#y0sR_C$= zGRXf!T)+es%E|vvp+K-g@}X%tBMBt`<$^FO+^;Ye1o|^L1}V@P|5YfH>YOjDG|bU; z$}n+~_ohLGf=_hxqDIG4(szDm)u#qjDCK-2&g2fdh3dho8UD~U!N_VD*TNGt z{8|dUrH!;s&;H3my7{WN|JEoR9)4^9_+FekcCv#t3R0dBwa(_9Sht+PspFR|yZwNW z1^IL{Z!AmP9fRQ)$Y4m(tLIx011u)Nn(06R&46W6(We;Vv*V(#!}Nv(e)NcwmB|}) z;6QqH<}}$2ZGgzkq;qL&rJFLFiq0I^9nW9CRZ{C}`VM$XVj2bg!i~+t6m}@S*LG#Q zleP7%gQZCf)->N=d0+kn%}77=m6`IV2;SA$<;M`+suJb7(n}iW65gu&IQnRt&m#z9 zRv3+25wTRR{05v5(=WCA;J&K%$b+aJVDnuR^XJ?-_#cLSuuQReFb79@>EsK~Fgn~z zgiDs2Cc!_{>}1lkS5orJUD)BI@^IaSr{vy)8%mk~gr_3!!c%ev{~*`$p6EJpxLBG^ zEVyvgRT>r=L@2UT34FY|=MA*s$;CR&BlgR2+wIdC9#K4bXV3kYMmO4ya&n|Js}ck$ zCxjg4m8Vuo&BD`}Ml4LE&u@p-m|9!N?GbRa*+XoHh}h2w6>s)U?854}t!>Ad43I6x zwfgmPRiI31L*EF{hD9Y$)<1@)vUAre;gPd-j#jNLb=`2fq*bcU_2?%4f<&dX6DwBp z0$u^fgld(P?WTFU*@64rzYg2gO^%P=%j2~BmT2W#gw(zpLYtLd48P%quvq*&af#JA zYK~$}_r`bSNE^MbG#w)7bX_0%_6Fy{$Ty`n2Aux$A8PhTcoHqbK`3=Q7+1>3C;x}- zAB3jQN3YnYMVAS(1A>A%Hyo(En>?DII4Hv=Uvl>gFxVPB`r3D%j_bQXh!`!Jd0oO$ z5@_m|#4zU{$04?AyMC*Cx=MDuu(amNlleRb93m?X{IVL{f=D;8kG10c<~Fs52H~59 zlkJd6D2VfquEfer?O)9Tx}%M+8H_`&_rl9J!WZBw3G5Tm%HQEy>sp_7hRzXN8<7T7oJHPR}mHOfB^wzV@;tTE0%>5PB5YswF%xg#^SvWp$< zNFXyV!QsM_y|?NI3ND3ej4CY(<*L|1dkxdX9;J*#bT&g-yBeXm`B}eau!pA?i9I># zp|Dh2oOG^!`)Xoe^^^eYTH7FF-3d*TbQ$Ds5wpVkYQC|tV&nMESh{d-!nPomlnt(bex=7I?vb+;$;FY)nQ0Wlkr z#rTYdQnv{w=}MDjh+m07VPo@~fe!`@XH3sFxD?QP6M24!HDY4PO-}cuZjsh?;dd=7 zoYZ|#7NmM|i;K|)eJ}e;RlML)QiCxbZRLbWI-4$UnpanT>cYo_67;$3(b4=5Q)`EP z2hsm36ezc@rPG+`J1GOJR1x5tsB_5ZcE&)2Mi)T*wI--ui{u-3g=*4??Zok9o_%ch zTi-l6(uU3OC>BCn#>mK37f6AsUr+poz$2*-3#Sp(jqIZ@bTp>t+u{vIOzoP54{b1T zH>gL^O3v><4fGjS(l~K^?%@R+E3*a@zdn%0DsF!wDVMwj)MJpD(x?ThSeC(O?BkDJ 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 literal 0 HcmV?d00001 From 5756e93e0e76076ecab7a834cd878cc11e56c9a7 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 4 Jan 2025 17:26:10 +0100 Subject: [PATCH 36/39] revert test trainer changes --- data/maps/Route102/scripts.inc | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/data/maps/Route102/scripts.inc b/data/maps/Route102/scripts.inc index 397398daee2..6131ef9e01e 100644 --- a/data/maps/Route102/scripts.inc +++ b/data/maps/Route102/scripts.inc @@ -64,17 +64,12 @@ Route102_EventScript_Rick:: end Route102_EventScript_Tiana:: - special ChooseHalfPartyForBattle - waitstate - multi_2_vs_2 TRAINER_TIANA, Route102_Text_TianaDefeated, TRAINER_ALLEN, Route102_Text_AllenDefeated, PARTNER_STEVEN -Route102_EventScript_TianaMsg:: + trainerbattle_single TRAINER_TIANA, Route102_Text_TianaIntro, Route102_Text_TianaDefeated msgbox Route102_Text_TianaPostBattle, MSGBOX_AUTOCLOSE end Route102_EventScript_Allen:: - special ChooseHalfPartyForBattle - waitstate - multi_2_vs_1 TRAINER_TIANA, Route102_Text_TianaDefeated, PARTNER_STEVEN + trainerbattle_single TRAINER_ALLEN, Route102_Text_AllenIntro, Route102_Text_AllenDefeated msgbox Route102_Text_AllenPostBattle, MSGBOX_AUTOCLOSE end From 00d215c8ccb14a94e2d6f04466edbd2fe54a6bb5 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 4 Jan 2025 19:22:05 +0100 Subject: [PATCH 37/39] fix rematches not triggering --- src/battle_setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index 29336f08486..82e6cee937e 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1095,11 +1095,13 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); } - SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why + SetMapVarsToTrainerA(); PUSH(EventSnippet_Lock); PUSH(EventSnippet_RevealTrainer); - if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { + DebugPrintfLevel(MGBA_LOG_DEBUG, "flag: %d, rematch: %d, ready: %d", GetTrainerFlag(), TRAINER_BATTLE_PARAM.isRematch, IsTrainerReadyForRematch()); + if ((GetTrainerFlag() && !TRAINER_BATTLE_PARAM.isRematch) + || (!IsTrainerReadyForRematch() && TRAINER_BATTLE_PARAM.isRematch)) { PUSH(EventSnippet_GotoPostBattleScript); return NULL; } From 3e3c0309ee47ff145d1af2d5382dc912f16a1230 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 4 Jan 2025 19:22:05 +0100 Subject: [PATCH 38/39] fix rematches not triggering --- src/battle_setup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index 29336f08486..5442bc24320 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1095,11 +1095,12 @@ const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data, PtrStack *scrStack, return BattleSetup_ConfigureTrainerBattleApproachingTrainer(data, scrStack); } - SetMapVarsToTrainerA(); // TODO check which cases exactly need this and why + SetMapVarsToTrainerA(); PUSH(EventSnippet_Lock); PUSH(EventSnippet_RevealTrainer); - if (GetTrainerFlag() || (TRAINER_BATTLE_PARAM.isRematch && !IsTrainerReadyForRematch())) { + if ((GetTrainerFlag() && !TRAINER_BATTLE_PARAM.isRematch) + || (!IsTrainerReadyForRematch() && TRAINER_BATTLE_PARAM.isRematch)) { PUSH(EventSnippet_GotoPostBattleScript); return NULL; } From 4ac2edb8b4f4255772e8493ac4b97b64c0ef8010 Mon Sep 17 00:00:00 2001 From: Sam Edding Date: Sat, 4 Jan 2025 20:01:26 +0100 Subject: [PATCH 39/39] fix one vs two trainer battle --- src/battle_setup.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index 5442bc24320..deee6f85f98 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1225,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);