summaryrefslogtreecommitdiff
path: root/src/pokenav_match_call_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pokenav_match_call_list.c')
-rwxr-xr-xsrc/pokenav_match_call_list.c521
1 files changed, 521 insertions, 0 deletions
diff --git a/src/pokenav_match_call_list.c b/src/pokenav_match_call_list.c
new file mode 100755
index 000000000..d56cfdb62
--- /dev/null
+++ b/src/pokenav_match_call_list.c
@@ -0,0 +1,521 @@
+#include "global.h"
+#include "battle_setup.h"
+#include "data.h"
+#include "event_data.h"
+#include "gym_leader_rematch.h"
+#include "international_string_util.h"
+#include "main.h"
+#include "match_call.h"
+#include "overworld.h"
+#include "pokemon.h"
+#include "pokenav.h"
+#include "sound.h"
+#include "string_util.h"
+#include "strings.h"
+#include "constants/songs.h"
+
+struct Pokenav_MatchCallMenu
+{
+ u16 optionCursorPos;
+ u16 maxOptionId;
+ const u8 *matchCallOptions;
+ u16 headerId;
+ u16 numRegistered;
+ u16 numSpecialTrainers;
+ bool32 initFinished;
+ u32 loopedTaskId;
+ u32 (*callback)(struct Pokenav_MatchCallMenu*);
+ struct PokenavMatchCallEntry matchCallEntries[MAX_REMATCH_ENTRIES - 1];
+};
+
+static u32 CB2_HandleMatchCallInput(struct Pokenav_MatchCallMenu *);
+static u32 GetExitMatchCallMenuId(struct Pokenav_MatchCallMenu *);
+static u32 CB2_HandleMatchCallOptionsInput(struct Pokenav_MatchCallMenu *);
+static u32 CB2_HandleCheckPageInput(struct Pokenav_MatchCallMenu *);
+static u32 CB2_HandleCallExitInput(struct Pokenav_MatchCallMenu *);
+static u32 LoopedTask_BuildMatchCallList(s32);
+static bool32 ShouldDoNearbyMessage(void);
+
+#include "data/text/match_call_messages.h"
+
+static const u8 sMatchCallOptionsNoCheckPage[] =
+{
+ MATCH_CALL_OPTION_CALL,
+ MATCH_CALL_OPTION_CANCEL
+};
+
+static const u8 sMatchCallOptionsHasCheckPage[] =
+{
+ MATCH_CALL_OPTION_CALL,
+ MATCH_CALL_OPTION_CHECK,
+ MATCH_CALL_OPTION_CANCEL
+};
+
+bool32 PokenavCallback_Init_MatchCall(void)
+{
+ struct Pokenav_MatchCallMenu *state = AllocSubstruct(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN, sizeof(struct Pokenav_MatchCallMenu));
+ if (!state)
+ return FALSE;
+
+ state->callback = CB2_HandleMatchCallInput;
+ state->headerId = 0;
+ state->initFinished = FALSE;
+ state->loopedTaskId = CreateLoopedTask(LoopedTask_BuildMatchCallList, 1);
+ return TRUE;
+}
+
+u32 GetMatchCallCallback(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->callback(state);
+}
+
+void FreeMatchCallSubstruct1(void)
+{
+ FreePokenavSubstruct(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+}
+
+static u32 CB2_HandleMatchCallInput(struct Pokenav_MatchCallMenu *state)
+{
+ int selection;
+
+ if (JOY_REPEAT(DPAD_UP))
+ return POKENAV_MC_FUNC_UP;
+ if (JOY_REPEAT(DPAD_DOWN))
+ return POKENAV_MC_FUNC_DOWN;
+ if (JOY_REPEAT(DPAD_LEFT))
+ return POKENAV_MC_FUNC_PG_UP;
+ if (JOY_REPEAT(DPAD_RIGHT))
+ return POKENAV_MC_FUNC_PG_DOWN;
+
+ if (JOY_NEW(A_BUTTON))
+ {
+ state->callback = CB2_HandleMatchCallOptionsInput;
+ state->optionCursorPos = 0;
+ selection = PokenavList_GetSelectedIndex();
+
+ if (!state->matchCallEntries[selection].isSpecialTrainer || MatchCall_HasCheckPage(state->matchCallEntries[selection].headerId))
+ {
+ state->matchCallOptions = sMatchCallOptionsHasCheckPage;
+ state->maxOptionId = ARRAY_COUNT(sMatchCallOptionsHasCheckPage) - 1;
+ }
+ else
+ {
+ state->matchCallOptions = sMatchCallOptionsNoCheckPage;
+ state->maxOptionId = ARRAY_COUNT(sMatchCallOptionsNoCheckPage) - 1;
+ }
+
+ return POKENAV_MC_FUNC_SELECT;
+ }
+
+ if (JOY_NEW(B_BUTTON))
+ {
+ if (GetPokenavMode() != POKENAV_MODE_FORCE_CALL_READY)
+ {
+ state->callback = GetExitMatchCallMenuId;
+ return POKENAV_MC_FUNC_EXIT;
+ }
+ else
+ {
+ // Cant exit Match Call menu before calling Mr Stone during tutorial
+ PlaySE(SE_FAILURE);
+ }
+ }
+
+ return POKENAV_MC_FUNC_NONE;
+}
+
+static u32 GetExitMatchCallMenuId(struct Pokenav_MatchCallMenu *state)
+{
+ return POKENAV_MAIN_MENU_CURSOR_ON_MATCH_CALL;
+}
+
+static u32 CB2_HandleMatchCallOptionsInput(struct Pokenav_MatchCallMenu *state)
+{
+ if (JOY_NEW(DPAD_UP) && state->optionCursorPos)
+ {
+ state->optionCursorPos--;
+ return POKENAV_MC_FUNC_MOVE_OPTIONS_CURSOR;
+ }
+
+ if (JOY_NEW(DPAD_DOWN) && state->optionCursorPos < state->maxOptionId)
+ {
+ state->optionCursorPos++;
+ return POKENAV_MC_FUNC_MOVE_OPTIONS_CURSOR;
+ }
+
+ if (JOY_NEW(A_BUTTON))
+ {
+ switch (state->matchCallOptions[state->optionCursorPos])
+ {
+ case MATCH_CALL_OPTION_CANCEL:
+ state->callback = CB2_HandleMatchCallInput;
+ return POKENAV_MC_FUNC_CANCEL;
+ case MATCH_CALL_OPTION_CALL:
+ if (GetPokenavMode() == POKENAV_MODE_FORCE_CALL_READY)
+ SetPokenavMode(POKENAV_MODE_FORCE_CALL_EXIT);
+
+ state->callback = CB2_HandleCallExitInput;
+ if (ShouldDoNearbyMessage())
+ return POKENAV_MC_FUNC_NEARBY_MSG;
+
+ return POKENAV_MC_FUNC_CALL_MSG;
+ case MATCH_CALL_OPTION_CHECK:
+ state->callback = CB2_HandleCheckPageInput;
+ return POKENAV_MC_FUNC_SHOW_CHECK_PAGE;
+ }
+ }
+
+ if (JOY_NEW(B_BUTTON))
+ {
+ state->callback = CB2_HandleMatchCallInput;
+ return POKENAV_MC_FUNC_CANCEL;
+ }
+
+ return POKENAV_MC_FUNC_NONE;
+}
+
+static u32 CB2_HandleCheckPageInput(struct Pokenav_MatchCallMenu *state)
+{
+ if (JOY_REPEAT(DPAD_UP))
+ return POKENAV_MC_FUNC_CHECK_PAGE_UP;
+ if (JOY_REPEAT(DPAD_DOWN))
+ return POKENAV_MC_FUNC_CHECK_PAGE_DOWN;
+
+ if (JOY_NEW(B_BUTTON))
+ {
+ state->callback = CB2_HandleMatchCallInput;
+ return POKENAV_MC_FUNC_EXIT_CHECK_PAGE;
+ }
+
+ return POKENAV_MC_FUNC_NONE;
+}
+
+static u32 CB2_HandleCallExitInput(struct Pokenav_MatchCallMenu *state)
+{
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ state->callback = CB2_HandleMatchCallInput;
+ return POKENAV_MC_FUNC_EXIT_CALL;
+ }
+
+ return POKENAV_MC_FUNC_NONE;
+}
+
+static u32 LoopedTask_BuildMatchCallList(s32 taskState)
+{
+ int i, j;
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ switch (taskState)
+ {
+ case 0:
+ state->headerId = 0;
+ state->numRegistered = 0;
+ return LT_INC_AND_CONTINUE;
+ case 1:
+ // Load special trainers (e.g. Rival, gym leaders)
+ for (i = 0, j = state->headerId; i < 30; i++, j++)
+ {
+ if (MatchCall_GetEnabled(j))
+ {
+ state->matchCallEntries[state->numRegistered].headerId = j;
+ state->matchCallEntries[state->numRegistered].isSpecialTrainer = TRUE;
+ state->matchCallEntries[state->numRegistered].mapSec = MatchCall_GetMapSec(j);
+ state->numRegistered++;
+ }
+
+ if (++state->headerId >= MC_HEADER_COUNT)
+ {
+ state->numSpecialTrainers = state->headerId;
+ state->headerId = 0;
+ return LT_INC_AND_CONTINUE;
+ }
+ }
+
+ return LT_CONTINUE;
+ case 2:
+ // Load normal trainers
+ for (i = 0, j = state->headerId; i < 30; i++, j++)
+ {
+ if (!MatchCall_HasRematchId(state->headerId) && IsRematchEntryRegistered(state->headerId))
+ {
+ state->matchCallEntries[state->numRegistered].headerId = state->headerId;
+ state->matchCallEntries[state->numRegistered].isSpecialTrainer = FALSE;
+ state->matchCallEntries[state->numRegistered].mapSec = GetMatchTableMapSectionId(j);
+ state->numRegistered++;
+ }
+
+ if (++state->headerId > REMATCH_TABLE_ENTRIES - 1)
+ return LT_INC_AND_CONTINUE;
+ }
+
+ return LT_CONTINUE;
+ case 3:
+ state->initFinished = TRUE;
+ break;
+ }
+
+ return LT_FINISH;
+}
+
+bool32 IsRematchEntryRegistered(int rematchIndex)
+{
+ if (rematchIndex < REMATCH_TABLE_ENTRIES)
+ return FlagGet(FLAG_MATCH_CALL_REGISTERED + rematchIndex);
+
+ return FALSE;
+}
+
+int IsMatchCallListInitFinished(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->initFinished;
+}
+
+int GetNumberRegistered(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->numRegistered;
+}
+
+// Unused
+static int GetNumSpecialTrainers(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->numSpecialTrainers;
+}
+
+// Unused
+static int GetNumNormalTrainers(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->numRegistered - state->numSpecialTrainers;
+}
+
+// Unused
+static int GetNormalTrainerHeaderId(int index)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ index += state->numSpecialTrainers;
+ if (index >= state->numRegistered)
+ return REMATCH_TABLE_ENTRIES;
+
+ return state->matchCallEntries[index].headerId;
+}
+
+struct PokenavMatchCallEntry *GetMatchCallList(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->matchCallEntries;
+}
+
+u16 GetMatchCallMapSec(int index)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->matchCallEntries[index].mapSec;
+}
+
+bool32 ShouldDrawRematchPokeballIcon(int index)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ if (!state->matchCallEntries[index].isSpecialTrainer)
+ index = state->matchCallEntries[index].headerId;
+ else
+ index = MatchCall_GetRematchTableIdx(state->matchCallEntries[index].headerId);
+
+ if (index == REMATCH_TABLE_ENTRIES)
+ return FALSE;
+
+ return gSaveBlock1Ptr->trainerRematches[index] != 0;
+}
+
+int GetMatchCallTrainerPic(int index)
+{
+ int headerId;
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ if (!state->matchCallEntries[index].isSpecialTrainer)
+ {
+ index = GetTrainerIdxByRematchIdx(state->matchCallEntries[index].headerId);
+ return gTrainers[index].trainerPic;
+ }
+
+ headerId = state->matchCallEntries[index].headerId;
+ index = MatchCall_GetRematchTableIdx(headerId);
+ if (index != REMATCH_TABLE_ENTRIES)
+ {
+ index = GetTrainerIdxByRematchIdx(index);
+ return gTrainers[index].trainerPic;
+ }
+
+ index = MatchCall_GetOverrideFacilityClass(headerId);
+ return gFacilityClassToPicIndex[index];
+}
+
+const u8 *GetMatchCallMessageText(int index, bool8 *newRematchRequest)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ *newRematchRequest = FALSE;
+ if (!Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType))
+ return gText_CallCantBeMadeHere;
+
+ if (!state->matchCallEntries[index].isSpecialTrainer)
+ *newRematchRequest = SelectMatchCallMessage(GetTrainerIdxByRematchIdx(state->matchCallEntries[index].headerId), gStringVar4);
+ else
+ MatchCall_GetMessage(state->matchCallEntries[index].headerId, gStringVar4);
+
+ return gStringVar4;
+}
+
+const u8 *GetMatchCallFlavorText(int index, int checkPageEntry)
+{
+ int rematchId;
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ if (state->matchCallEntries[index].isSpecialTrainer)
+ {
+ rematchId = MatchCall_GetRematchTableIdx(state->matchCallEntries[index].headerId);
+ if (rematchId == REMATCH_TABLE_ENTRIES)
+ return MatchCall_GetOverrideFlavorText(state->matchCallEntries[index].headerId, checkPageEntry);
+ }
+ else
+ {
+ rematchId = state->matchCallEntries[index].headerId;
+ }
+
+ return gMatchCallFlavorTexts[rematchId][checkPageEntry];
+}
+
+u16 GetMatchCallOptionCursorPos(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ return state->optionCursorPos;
+}
+
+u16 GetMatchCallOptionId(int optionId)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ if (state->maxOptionId < optionId)
+ return MATCH_CALL_OPTION_COUNT;
+
+ return state->matchCallOptions[optionId];
+}
+
+void BufferMatchCallNameAndDesc(struct PokenavMatchCallEntry *matchCallEntry, u8 *str)
+{
+ const u8 *trainerName;
+ const u8 *className;
+ if (!matchCallEntry->isSpecialTrainer)
+ {
+ int index = GetTrainerIdxByRematchIdx(matchCallEntry->headerId);
+ const struct Trainer *trainer = &gTrainers[index];
+ int class = trainer->trainerClass;
+ className = gTrainerClassNames[class];
+ trainerName = trainer->trainerName;
+ }
+ else
+ {
+ MatchCall_GetNameAndDesc(matchCallEntry->headerId, &className, &trainerName);
+ }
+
+ if (className && trainerName)
+ {
+ u8 *str2 = GetStringClearToWidth(str, FONT_NARROW, className, 69);
+ GetStringClearToWidth(str2, FONT_NARROW, trainerName, 51);
+ }
+ else
+ {
+ GetStringClearToWidth(str, FONT_NARROW, NULL, 120);
+ }
+}
+
+u8 GetMatchTableMapSectionId(int rematchIndex)
+{
+ int mapGroup = gRematchTable[rematchIndex].mapGroup;
+ int mapNum = gRematchTable[rematchIndex].mapNum;
+ return Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum)->regionMapSectionId;
+}
+
+int GetIndexDeltaOfNextCheckPageDown(int index)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ int count = 1;
+ while (++index < state->numRegistered)
+ {
+ if (!state->matchCallEntries[index].isSpecialTrainer)
+ return count;
+ if (MatchCall_HasCheckPage(state->matchCallEntries[index].headerId))
+ return count;
+
+ count++;
+ }
+
+ return 0;
+}
+
+int GetIndexDeltaOfNextCheckPageUp(int index)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ int count = -1;
+ while (--index >= 0)
+ {
+ if (!state->matchCallEntries[index].isSpecialTrainer)
+ return count;
+ if (MatchCall_HasCheckPage(state->matchCallEntries[index].headerId))
+ return count;
+
+ count--;
+ }
+
+ return 0;
+}
+
+// Unused
+static bool32 HasRematchEntry(void)
+{
+ int i;
+
+ for (i = 0; i < REMATCH_TABLE_ENTRIES; i++)
+ {
+ if (IsRematchEntryRegistered(i) && gSaveBlock1Ptr->trainerRematches[i])
+ return TRUE;
+ }
+
+ for (i = 0; i < MC_HEADER_COUNT; i++)
+ {
+ if (MatchCall_GetEnabled(i))
+ {
+ int index = MatchCall_GetRematchTableIdx(i);
+ if (gSaveBlock1Ptr->trainerRematches[index])
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static bool32 ShouldDoNearbyMessage(void)
+{
+ struct Pokenav_MatchCallMenu *state = GetSubstructPtr(POKENAV_SUBSTRUCT_MATCH_CALL_MAIN);
+ int selection = PokenavList_GetSelectedIndex();
+ if (!state->matchCallEntries[selection].isSpecialTrainer)
+ {
+ if (GetMatchCallMapSec(selection) == gMapHeader.regionMapSectionId)
+ {
+ if (!gSaveBlock1Ptr->trainerRematches[state->matchCallEntries[selection].headerId])
+ return TRUE;
+ }
+ }
+ else
+ {
+ if (state->matchCallEntries[selection].headerId == MC_HEADER_WATTSON)
+ {
+ if (GetMatchCallMapSec(selection) == gMapHeader.regionMapSectionId
+ && FlagGet(FLAG_BADGE05_GET) == TRUE)
+ {
+ if (!FlagGet(FLAG_WATTSON_REMATCH_AVAILABLE))
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}