pokeemerald/src/cable_club.c

1335 lines
34 KiB
C
Raw Normal View History

2018-10-11 23:02:58 +02:00
#include "global.h"
#include "main.h"
2018-10-13 19:41:10 +02:00
#include "battle.h"
#include "battle_records.h"
#include "battle_setup.h"
#include "cable_club.h"
2019-04-04 23:53:06 +02:00
#include "data.h"
2018-10-13 19:41:10 +02:00
#include "event_data.h"
#include "field_message_box.h"
#include "field_specials.h"
#include "field_weather.h"
2018-10-11 23:02:58 +02:00
#include "international_string_util.h"
#include "link.h"
2018-10-13 19:41:10 +02:00
#include "link_rfu.h"
#include "load_save.h"
#include "m4a.h"
2018-10-11 23:02:58 +02:00
#include "menu.h"
2018-10-13 19:41:10 +02:00
#include "overworld.h"
#include "palette.h"
2019-03-30 19:36:52 +01:00
#include "union_room.h"
#include "mystery_gift.h"
2018-10-13 19:41:10 +02:00
#include "script.h"
#include "script_pokemon_util.h"
2018-10-13 19:41:10 +02:00
#include "sound.h"
#include "start_menu.h"
2018-10-11 23:02:58 +02:00
#include "string_util.h"
#include "strings.h"
2018-10-13 19:41:10 +02:00
#include "task.h"
#include "trade.h"
#include "trainer_card.h"
2019-02-02 12:44:00 +01:00
#include "party_menu.h"
2018-10-13 19:41:10 +02:00
#include "window.h"
2019-10-11 10:14:09 +02:00
#include "constants/battle_frontier.h"
#include "constants/cable_club.h"
2018-10-13 19:41:10 +02:00
#include "constants/songs.h"
2020-06-04 00:00:53 +02:00
#include "constants/trainers.h"
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
static const struct WindowTemplate sWindowTemplate_LinkPlayerCount = {
2018-10-27 00:53:07 +02:00
.bg = 0,
2018-10-13 19:41:10 +02:00
.tilemapLeft = 16,
.tilemapTop = 11,
.width = 11,
.height = 2,
.paletteNum = 15,
.baseBlock = 0x0125,
};
2020-06-04 00:00:53 +02:00
static const u8 *const sTrainerCardColorNames[] = {
2018-10-13 19:41:10 +02:00
gText_BronzeCard,
gText_CopperCard,
gText_SilverCard,
gText_GoldCard
};
2018-10-11 23:02:58 +02:00
2020-06-04 00:00:53 +02:00
static void Task_LinkupStart(u8 taskId);
static void Task_LinkupAwaitConnection(u8 taskId);
static void Task_LinkupConfirmWhenReady(u8 taskId);
static void Task_LinkupAwaitConfirmation(u8 taskId);
static void Task_LinkupTryConfirmation(u8 taskId);
static void Task_LinkupConfirm(u8 taskId);
static void Task_LinkupExchangeDataWithLeader(u8 taskId);
static void Task_LinkupCheckStatusAfterConfirm(u8 taskId);
static void Task_LinkupAwaitTrainerCardData(u8 taskId);
static void Task_StopLinkup(u8 taskId);
static void Task_LinkupFailed(u8 taskId);
static void Task_LinkupConnectionError(u8 taskId);
static bool8 TryLinkTimeout(u8 taskId);
static void Task_ValidateMixingGameLanguage(u8 taskId);
static void Task_ReestablishLink(u8 taskId);
static void Task_ReestablishLinkAwaitConnection(u8 taskId);
static void Task_ReestablishLinkLeader(u8 taskId);
static void Task_ReestablishLinkAwaitConfirmation(u8 taskId);
#define tState data[0]
#define tMinPlayers data[1]
#define tMaxPlayers data[2]
#define tNumPlayers data[3]
#define tTimer data[4]
#define tWindowId data[5]
static void CreateLinkupTask(u8 minPlayers, u8 maxPlayers)
2018-10-11 23:02:58 +02:00
{
2021-02-20 05:22:26 +01:00
if (FindTaskIdByFunc(Task_LinkupStart) == TASK_NONE)
2018-10-11 23:02:58 +02:00
{
u8 taskId1;
2020-06-04 00:00:53 +02:00
taskId1 = CreateTask(Task_LinkupStart, 80);
gTasks[taskId1].tMinPlayers = minPlayers;
gTasks[taskId1].tMaxPlayers = maxPlayers;
2018-10-11 23:02:58 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void PrintNumPlayersInLink(u16 windowId, u32 numPlayers)
2018-10-11 23:02:58 +02:00
{
u8 xPos;
2020-06-04 00:00:53 +02:00
ConvertIntToDecimalStringN(gStringVar1, numPlayers, STR_CONV_MODE_LEFT_ALIGN, 1);
2022-07-25 20:59:14 +02:00
SetStandardWindowBorderStyle(windowId, FALSE);
2020-06-04 00:00:53 +02:00
StringExpandPlaceholders(gStringVar4, gText_NumPlayerLink);
2021-10-30 22:47:37 +02:00
xPos = GetStringCenterAlignXOffset(FONT_NORMAL, gStringVar4, 88);
AddTextPrinterParameterized(windowId, FONT_NORMAL, gStringVar4, xPos, 1, TEXT_SKIP_DRAW, NULL);
2021-11-03 20:29:18 +01:00
CopyWindowToVram(windowId, COPYWIN_FULL);
2018-10-11 23:02:58 +02:00
}
2020-06-04 00:00:53 +02:00
static void ClearLinkPlayerCountWindow(u16 windowId)
2018-10-11 23:02:58 +02:00
{
2021-11-03 20:29:18 +01:00
// Following this call with a copy-to-vram with mode COPYWIN_FULL is identical to
// calling ClearStdWindowAndFrame(windowId, TRUE).
ClearStdWindowAndFrame(windowId, FALSE);
2021-11-03 20:29:18 +01:00
CopyWindowToVram(windowId, COPYWIN_FULL);
2018-10-11 23:02:58 +02:00
}
2020-06-04 00:00:53 +02:00
static void UpdateLinkPlayerCountDisplay(u8 taskId, u8 numPlayers)
2018-10-11 23:02:58 +02:00
{
s16 *data = gTasks[taskId].data;
2020-06-04 00:00:53 +02:00
if (numPlayers != tNumPlayers)
2018-10-11 23:02:58 +02:00
{
2020-06-04 00:00:53 +02:00
if (numPlayers <= 1)
ClearLinkPlayerCountWindow(tWindowId);
2018-10-11 23:02:58 +02:00
else
2020-06-04 00:00:53 +02:00
PrintNumPlayersInLink(tWindowId, numPlayers);
tNumPlayers = numPlayers;
2018-10-11 23:02:58 +02:00
}
}
2020-06-04 00:00:53 +02:00
static u32 ExchangeDataAndGetLinkupStatus(u8 minPlayers, u8 maxPlayers)
2018-10-11 23:02:58 +02:00
{
2020-06-04 00:00:53 +02:00
switch (GetLinkPlayerDataExchangeStatusTimed(minPlayers, maxPlayers))
2018-10-11 23:02:58 +02:00
{
case EXCHANGE_COMPLETE:
2020-06-04 00:00:53 +02:00
return LINKUP_SUCCESS;
case EXCHANGE_DIFF_SELECTIONS:
return LINKUP_DIFF_SELECTIONS;
2019-10-10 09:50:51 +02:00
case EXCHANGE_PLAYER_NOT_READY:
2020-06-04 00:00:53 +02:00
return LINKUP_PLAYER_NOT_READY;
2019-10-10 09:50:51 +02:00
case EXCHANGE_PARTNER_NOT_READY:
2020-06-04 00:00:53 +02:00
return LINKUP_PARTNER_NOT_READY;
case EXCHANGE_WRONG_NUM_PLAYERS:
2018-10-11 23:02:58 +02:00
ConvertIntToDecimalStringN(gStringVar1, GetLinkPlayerCount_2(), STR_CONV_MODE_LEFT_ALIGN, 1);
2020-06-04 00:00:53 +02:00
return LINKUP_WRONG_NUM_PLAYERS;
2018-10-11 23:02:58 +02:00
case EXCHANGE_STAT_7:
2020-06-04 00:00:53 +02:00
return LINKUP_FAILED_CONTEST_GMODE;
2018-10-11 23:02:58 +02:00
case EXCHANGE_TIMED_OUT:
default:
2020-06-04 00:00:53 +02:00
return LINKUP_ONGOING;
2018-10-11 23:02:58 +02:00
}
}
2020-06-04 00:00:53 +02:00
static bool32 CheckLinkErrored(u8 taskId)
2018-10-11 23:02:58 +02:00
{
if (HasLinkErrorOccurred() == TRUE)
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConnectionError;
2018-10-11 23:02:58 +02:00
return TRUE;
}
return FALSE;
}
2020-06-04 00:00:53 +02:00
static bool32 CheckLinkCanceledBeforeConnection(u8 taskId)
2018-10-11 23:02:58 +02:00
{
2020-09-05 03:11:55 +02:00
if ((JOY_NEW(B_BUTTON))
2018-10-11 23:02:58 +02:00
&& IsLinkConnectionEstablished() == FALSE)
{
gLinkType = 0;
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupFailed;
2018-10-11 23:02:58 +02:00
return TRUE;
}
return FALSE;
}
2020-06-04 00:00:53 +02:00
static bool32 CheckLinkCanceled(u8 taskId)
2018-10-11 23:02:58 +02:00
{
if (IsLinkConnectionEstablished())
SetSuppressLinkErrorMessage(TRUE);
2020-09-05 03:11:55 +02:00
if (JOY_NEW(B_BUTTON))
2018-10-11 23:02:58 +02:00
{
gLinkType = 0;
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupFailed;
2018-10-11 23:02:58 +02:00
return TRUE;
}
return FALSE;
}
static bool32 CheckSioErrored(u8 taskId)
2018-10-11 23:02:58 +02:00
{
if (GetSioMultiSI() == TRUE)
2018-10-11 23:02:58 +02:00
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConnectionError;
2018-10-11 23:02:58 +02:00
return TRUE;
}
return FALSE;
}
2020-06-04 00:00:53 +02:00
// Unused
static void Task_DelayedBlockRequest(u8 taskId)
2018-10-11 23:02:58 +02:00
{
gTasks[taskId].data[0]++;
if (gTasks[taskId].data[0] == 10)
{
SendBlockRequest(BLOCK_REQ_SIZE_100);
2018-10-11 23:02:58 +02:00
DestroyTask(taskId);
}
}
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
static void Task_LinkupStart(u8 taskId)
2018-10-13 19:41:10 +02:00
{
s16 *data = gTasks[taskId].data;
if (data[0] == 0)
{
OpenLinkTimed();
ResetLinkPlayerCount();
2018-10-13 19:41:10 +02:00
ResetLinkPlayers();
2020-06-04 00:00:53 +02:00
tWindowId = AddWindow(&sWindowTemplate_LinkPlayerCount);
2018-10-13 19:41:10 +02:00
}
else if (data[0] > 9)
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupAwaitConnection;
2018-10-13 19:41:10 +02:00
}
data[0]++;
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupAwaitConnection(u8 taskId)
2018-10-13 19:41:10 +02:00
{
u32 playerCount = GetLinkPlayerCount_2();
2020-06-04 00:00:53 +02:00
if (CheckLinkCanceledBeforeConnection(taskId) == TRUE
|| CheckLinkCanceled(taskId) == TRUE
2018-10-13 19:41:10 +02:00
|| playerCount < 2)
return;
SetSuppressLinkErrorMessage(TRUE);
gTasks[taskId].data[3] = 0;
if (IsLinkMaster() == TRUE)
{
PlaySE(SE_PIN);
ShowFieldAutoScrollMessage(gText_ConfirmLinkWhenPlayersReady);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConfirmWhenReady;
2018-10-13 19:41:10 +02:00
}
else
{
PlaySE(SE_BOO);
ShowFieldAutoScrollMessage(gText_AwaitingLinkup);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupExchangeDataWithLeader;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupConfirmWhenReady(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (CheckLinkCanceledBeforeConnection(taskId) == TRUE
|| CheckSioErrored(taskId) == TRUE
2020-06-04 00:00:53 +02:00
|| CheckLinkErrored(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
if (GetFieldMessageBoxMode() == FIELD_MESSAGE_BOX_HIDDEN)
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].tNumPlayers = 0;
gTasks[taskId].func = Task_LinkupAwaitConfirmation;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupAwaitConfirmation(u8 taskId)
2018-10-13 19:41:10 +02:00
{
s16 *data = gTasks[taskId].data;
s32 linkPlayerCount = GetLinkPlayerCount_2();
2020-06-04 00:00:53 +02:00
if (CheckLinkCanceledBeforeConnection(taskId) == TRUE
|| CheckSioErrored(taskId) == TRUE
2020-06-04 00:00:53 +02:00
|| CheckLinkErrored(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
2020-06-04 00:00:53 +02:00
UpdateLinkPlayerCountDisplay(taskId, linkPlayerCount);
2018-10-13 19:41:10 +02:00
2020-09-05 03:11:55 +02:00
if (!(JOY_NEW(A_BUTTON)))
2018-10-13 19:41:10 +02:00
return;
2020-06-04 00:00:53 +02:00
if (linkPlayerCount < tMinPlayers)
2018-10-13 19:41:10 +02:00
return;
SaveLinkPlayers(linkPlayerCount);
2020-06-04 00:00:53 +02:00
ClearLinkPlayerCountWindow(tWindowId);
2018-10-13 19:41:10 +02:00
ConvertIntToDecimalStringN(gStringVar1, linkPlayerCount, STR_CONV_MODE_LEFT_ALIGN, 1);
ShowFieldAutoScrollMessage(gText_ConfirmStartLinkWithXPlayers);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupTryConfirmation;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupTryConfirmation(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (CheckLinkCanceledBeforeConnection(taskId) == TRUE
|| CheckSioErrored(taskId) == TRUE
2020-06-04 00:00:53 +02:00
|| CheckLinkErrored(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
if (GetFieldMessageBoxMode() == FIELD_MESSAGE_BOX_HIDDEN)
{
if (GetSavedPlayerCount() != GetLinkPlayerCount_2())
2018-10-13 19:41:10 +02:00
{
ShowFieldAutoScrollMessage(gText_ConfirmLinkWhenPlayersReady);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConfirmWhenReady;
2018-10-13 19:41:10 +02:00
}
2020-09-05 03:11:55 +02:00
else if (JOY_HELD(B_BUTTON))
2018-10-13 19:41:10 +02:00
{
ShowFieldAutoScrollMessage(gText_ConfirmLinkWhenPlayersReady);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConfirmWhenReady;
2018-10-13 19:41:10 +02:00
}
2020-09-05 03:11:55 +02:00
else if (JOY_HELD(A_BUTTON))
2018-10-13 19:41:10 +02:00
{
PlaySE(SE_SELECT);
CheckShouldAdvanceLinkState();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConfirm;
2018-10-13 19:41:10 +02:00
}
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupConfirm(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
u8 minPlayers = gTasks[taskId].tMinPlayers;
u8 maxPlayers = gTasks[taskId].tMaxPlayers;
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
if (CheckLinkErrored(taskId) == TRUE
|| TryLinkTimeout(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
if (GetLinkPlayerCount_2() != GetSavedPlayerCount())
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConnectionError;
2018-10-13 19:41:10 +02:00
}
else
{
2020-06-04 00:00:53 +02:00
gSpecialVar_Result = ExchangeDataAndGetLinkupStatus(minPlayers, maxPlayers);
if (gSpecialVar_Result != LINKUP_ONGOING)
gTasks[taskId].func = Task_LinkupCheckStatusAfterConfirm;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupExchangeDataWithLeader(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
u8 minPlayers, maxPlayers;
2018-10-13 19:41:10 +02:00
struct TrainerCard *card;
2020-06-04 00:00:53 +02:00
minPlayers = gTasks[taskId].tMinPlayers;
maxPlayers = gTasks[taskId].tMaxPlayers;
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
if (CheckLinkCanceledBeforeConnection(taskId) == TRUE
|| CheckLinkErrored(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
2020-06-04 00:00:53 +02:00
gSpecialVar_Result = ExchangeDataAndGetLinkupStatus(minPlayers, maxPlayers);
if (gSpecialVar_Result == LINKUP_ONGOING)
2018-10-13 19:41:10 +02:00
return;
if (gSpecialVar_Result == LINKUP_DIFF_SELECTIONS
2020-06-04 00:00:53 +02:00
|| gSpecialVar_Result == LINKUP_WRONG_NUM_PLAYERS)
2018-10-13 19:41:10 +02:00
{
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2018-10-13 19:41:10 +02:00
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
else if (gSpecialVar_Result == LINKUP_PLAYER_NOT_READY
2020-06-04 00:00:53 +02:00
|| gSpecialVar_Result == LINKUP_PARTNER_NOT_READY)
2018-10-13 19:41:10 +02:00
{
CloseLink();
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
else
{
gFieldLinkPlayerCount = GetLinkPlayerCount_2();
2019-02-27 04:04:44 +01:00
gLocalLinkPlayerId = GetMultiplayerId();
SaveLinkPlayers(gFieldLinkPlayerCount);
2018-10-13 19:41:10 +02:00
card = (struct TrainerCard *)gBlockSendBuffer;
2021-10-15 18:05:19 +02:00
TrainerCard_GenerateCardForLinkPlayer(card);
2018-11-25 22:50:54 +01:00
card->monSpecies[0] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[0] - 1], MON_DATA_SPECIES, NULL);
card->monSpecies[1] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[1] - 1], MON_DATA_SPECIES, NULL);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupAwaitTrainerCardData;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupCheckStatusAfterConfirm(u8 taskId)
2018-10-13 19:41:10 +02:00
{
struct TrainerCard *card;
2020-06-04 00:00:53 +02:00
if (CheckLinkErrored(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
2020-06-04 00:00:53 +02:00
if (gSpecialVar_Result == LINKUP_WRONG_NUM_PLAYERS)
2018-10-13 19:41:10 +02:00
{
if (!Link_AnyPartnersPlayingRubyOrSapphire())
{
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2018-10-13 19:41:10 +02:00
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
else
{
CloseLink();
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
else if (gSpecialVar_Result == LINKUP_DIFF_SELECTIONS)
2018-10-13 19:41:10 +02:00
{
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2018-10-13 19:41:10 +02:00
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
else if (gSpecialVar_Result == LINKUP_PLAYER_NOT_READY
2020-06-04 00:00:53 +02:00
|| gSpecialVar_Result == LINKUP_PARTNER_NOT_READY)
2018-10-13 19:41:10 +02:00
{
CloseLink();
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
else
{
gFieldLinkPlayerCount = GetLinkPlayerCount_2();
2019-02-27 04:04:44 +01:00
gLocalLinkPlayerId = GetMultiplayerId();
SaveLinkPlayers(gFieldLinkPlayerCount);
2018-10-13 19:41:10 +02:00
card = (struct TrainerCard *)gBlockSendBuffer;
2021-10-15 18:05:19 +02:00
TrainerCard_GenerateCardForLinkPlayer(card);
2018-11-25 22:50:54 +01:00
card->monSpecies[0] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[0] - 1], MON_DATA_SPECIES, NULL);
card->monSpecies[1] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[1] - 1], MON_DATA_SPECIES, NULL);
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupAwaitTrainerCardData;
SendBlockRequest(BLOCK_REQ_SIZE_100);
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
bool32 AreBattleTowerLinkSpeciesSame(u16 *speciesList1, u16 *speciesList2)
2018-10-13 19:41:10 +02:00
{
int i;
int j;
2020-06-04 00:00:53 +02:00
bool32 haveSameSpecies = FALSE;
int numSameSpecies = 0;
2018-10-13 19:41:10 +02:00
gStringVar1[0] = EOS;
gStringVar2[0] = EOS;
2018-10-27 00:53:07 +02:00
2020-06-04 00:00:53 +02:00
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
for (j = 0; j < FRONTIER_MULTI_PARTY_SIZE; j++)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (speciesList1[i] == speciesList2[j])
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (numSameSpecies == 0)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
StringCopy(gStringVar1, gSpeciesNames[speciesList1[i]]);
haveSameSpecies = TRUE;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
if (numSameSpecies == 1)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
StringCopy(gStringVar2, gSpeciesNames[speciesList1[i]]);
haveSameSpecies = TRUE;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
numSameSpecies++;
2018-10-13 19:41:10 +02:00
}
}
}
2020-06-04 00:00:53 +02:00
// var below is read by BattleFrontier_BattleTowerLobby_EventScript_AbortLink
gSpecialVar_0x8005 = numSameSpecies;
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
return haveSameSpecies;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
static void FinishLinkup(u16 *linkupStatus, u32 taskId)
2018-10-13 19:41:10 +02:00
{
struct TrainerCard *trainerCards = gTrainerCards;
2020-06-04 00:00:53 +02:00
if (*linkupStatus == LINKUP_SUCCESS)
2018-10-13 19:41:10 +02:00
{
2019-10-11 10:14:09 +02:00
if (gLinkType == LINKTYPE_BATTLE_TOWER_50 || gLinkType == LINKTYPE_BATTLE_TOWER_OPEN)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (AreBattleTowerLinkSpeciesSame(trainerCards[0].monSpecies, trainerCards[1].monSpecies))
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
// Unsuccessful battle tower linkup
*linkupStatus = LINKUP_FAILED_BATTLE_TOWER;
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
else
{
2020-06-04 00:00:53 +02:00
// Successful battle tower linkup
ClearLinkPlayerCountWindow(gTasks[taskId].tWindowId);
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
}
else
{
2020-06-04 00:00:53 +02:00
// Successful linkup
ClearLinkPlayerCountWindow(gTasks[taskId].tWindowId);
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
}
else
{
2020-06-04 00:00:53 +02:00
// Unsuccessful linkup
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_StopLinkup;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupAwaitTrainerCardData(u8 taskId)
2018-10-13 19:41:10 +02:00
{
u8 index;
2020-06-04 00:00:53 +02:00
if (CheckLinkErrored(taskId) == TRUE)
2018-10-13 19:41:10 +02:00
return;
if (GetBlockReceivedStatus() != GetSavedLinkPlayerCountAsBitFlags())
2018-10-13 19:41:10 +02:00
return;
for (index = 0; index < GetLinkPlayerCount(); index++)
{
2021-10-15 18:05:19 +02:00
CopyTrainerCardData(&gTrainerCards[index], (struct TrainerCard *)gBlockRecvBuffer[index], gLinkPlayers[index].version);
2018-10-13 19:41:10 +02:00
}
SetSuppressLinkErrorMessage(FALSE);
ResetBlockReceivedFlags();
2020-06-04 00:00:53 +02:00
FinishLinkup(&gSpecialVar_Result, taskId);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
static void Task_StopLinkup(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (!gReceivedRemoteLinkPlayers)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
ClearLinkPlayerCountWindow(gTasks[taskId].tWindowId);
ScriptContext_Enable();
2020-06-04 00:00:53 +02:00
RemoveWindow(gTasks[taskId].tWindowId);
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupFailed(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gSpecialVar_Result = LINKUP_FAILED;
ClearLinkPlayerCountWindow(gTasks[taskId].tWindowId);
StopFieldMessage();
RemoveWindow(gTasks[taskId].tWindowId);
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
2020-06-04 00:00:53 +02:00
static void Task_LinkupConnectionError(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gSpecialVar_Result = LINKUP_CONNECTION_ERROR;
ClearLinkPlayerCountWindow(gTasks[taskId].tWindowId);
RemoveWindow(gTasks[taskId].tWindowId);
2018-10-13 19:41:10 +02:00
HideFieldMessageBox();
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
2020-06-04 00:00:53 +02:00
static bool8 TryLinkTimeout(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].tTimer++;
if (gTasks[taskId].tTimer > 600)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_LinkupConnectionError;
2018-10-13 19:41:10 +02:00
return TRUE;
}
return FALSE;
}
2020-06-04 00:00:53 +02:00
void TryBattleLinkup(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
u8 minPlayers = 2;
u8 maxPlayers = 2;
2018-10-13 19:41:10 +02:00
switch (gSpecialVar_0x8004)
{
2019-10-11 10:14:09 +02:00
case USING_SINGLE_BATTLE:
2020-06-04 00:00:53 +02:00
minPlayers = 2;
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_SINGLE_BATTLE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_DOUBLE_BATTLE:
2020-06-04 00:00:53 +02:00
minPlayers = 2;
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_DOUBLE_BATTLE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_MULTI_BATTLE:
2020-06-04 00:00:53 +02:00
minPlayers = 4;
maxPlayers = 4;
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_MULTI_BATTLE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_BATTLE_TOWER:
2020-06-04 00:00:53 +02:00
minPlayers = 2;
2019-10-11 10:14:09 +02:00
if (gSaveBlock2Ptr->frontier.lvlMode == FRONTIER_LVL_50)
gLinkType = LINKTYPE_BATTLE_TOWER_50;
2018-10-13 19:41:10 +02:00
else
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BATTLE_TOWER_OPEN;
2018-10-13 19:41:10 +02:00
break;
}
2020-06-04 00:00:53 +02:00
CreateLinkupTask(minPlayers, maxPlayers);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
#undef tMinPlayers
#undef tMaxPlayers
#undef tNumPlayers
#undef tTimer
#undef tWindowId
2019-10-11 10:14:09 +02:00
void TryTradeLinkup(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gLinkType = LINKTYPE_TRADE_SETUP;
2018-10-13 19:41:10 +02:00
gBattleTypeFlags = 0;
2020-06-04 00:00:53 +02:00
CreateLinkupTask(2, 2);
2018-10-13 19:41:10 +02:00
}
2020-01-08 21:46:49 +01:00
void TryRecordMixLinkup(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gSpecialVar_Result = LINKUP_ONGOING;
gLinkType = LINKTYPE_RECORD_MIX_BEFORE;
2018-10-13 19:41:10 +02:00
gBattleTypeFlags = 0;
2020-06-04 00:00:53 +02:00
CreateLinkupTask(2, 4);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
void ValidateMixingGameLanguage(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
u32 taskId = FindTaskIdByFunc(Task_ValidateMixingGameLanguage);
2018-10-13 19:41:10 +02:00
2021-02-20 05:22:26 +01:00
if (taskId == TASK_NONE)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
taskId = CreateTask(Task_ValidateMixingGameLanguage, 80);
gTasks[taskId].tState = 0;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_ValidateMixingGameLanguage(u8 taskId)
2018-10-13 19:41:10 +02:00
{
int playerCount;
int i;
2020-06-04 00:00:53 +02:00
switch (gTasks[taskId].tState)
2018-10-13 19:41:10 +02:00
{
case 0:
2020-06-04 00:00:53 +02:00
if (gSpecialVar_Result == LINKUP_SUCCESS)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
bool32 mixingForeignGames = FALSE;
2018-10-13 19:41:10 +02:00
bool32 isEnglishRSLinked = FALSE;
bool32 isJapaneseEmeraldLinked = FALSE;
playerCount = GetLinkPlayerCount();
for (i = 0; i < playerCount; i++)
{
u32 version = (u8)gLinkPlayers[i].version;
u32 language = gLinkPlayers[i].language;
if (version == VERSION_RUBY || version == VERSION_SAPPHIRE)
{
if (language == LANGUAGE_JAPANESE)
{
2020-06-04 00:00:53 +02:00
mixingForeignGames = TRUE;
2018-10-13 19:41:10 +02:00
break;
}
else
{
isEnglishRSLinked = TRUE;
}
}
else if (version == VERSION_EMERALD)
{
if (language == LANGUAGE_JAPANESE)
{
isJapaneseEmeraldLinked = TRUE;
}
}
}
if (isEnglishRSLinked && isJapaneseEmeraldLinked)
{
2020-06-04 00:00:53 +02:00
mixingForeignGames = TRUE;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
if (mixingForeignGames)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
gSpecialVar_Result = LINKUP_FOREIGN_GAME;
2020-08-13 09:09:47 +02:00
SetCloseLinkCallbackHandleJP();
2020-06-04 00:00:53 +02:00
gTasks[taskId].tState = 1;
2018-10-13 19:41:10 +02:00
return;
}
}
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
break;
case 1:
2020-06-04 00:00:53 +02:00
if (!gReceivedRemoteLinkPlayers)
2018-10-13 19:41:10 +02:00
{
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
break;
}
}
void TryBerryBlenderLinkup(void)
2018-10-13 19:41:10 +02:00
{
gLinkType = LINKTYPE_BERRY_BLENDER_SETUP;
2018-10-13 19:41:10 +02:00
gBattleTypeFlags = 0;
2020-06-04 00:00:53 +02:00
CreateLinkupTask(2, 4);
2018-10-13 19:41:10 +02:00
}
2019-11-11 03:54:00 +01:00
void TryContestGModeLinkup(void)
2018-10-13 19:41:10 +02:00
{
2019-11-11 03:54:00 +01:00
gLinkType = LINKTYPE_CONTEST_GMODE;
2018-10-13 19:41:10 +02:00
gBattleTypeFlags = 0;
2020-06-04 00:00:53 +02:00
CreateLinkupTask(4, 4);
2018-10-13 19:41:10 +02:00
}
2019-11-11 03:54:00 +01:00
void TryContestEModeLinkup(void)
2018-10-13 19:41:10 +02:00
{
2019-11-11 03:54:00 +01:00
gLinkType = LINKTYPE_CONTEST_EMODE;
2018-10-13 19:41:10 +02:00
gBattleTypeFlags = 0;
2020-06-04 00:00:53 +02:00
CreateLinkupTask(2, 4);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
u8 CreateTask_ReestablishCableClubLink(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (FuncIsActiveTask(Task_ReestablishLink) != FALSE)
2018-10-13 19:41:10 +02:00
return 0xFF;
switch (gSpecialVar_0x8004)
{
2019-10-11 10:14:09 +02:00
case USING_SINGLE_BATTLE:
gLinkType = LINKTYPE_SINGLE_BATTLE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_DOUBLE_BATTLE:
gLinkType = LINKTYPE_DOUBLE_BATTLE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_MULTI_BATTLE:
gLinkType = LINKTYPE_MULTI_BATTLE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_BATTLE_TOWER:
if (gSaveBlock2Ptr->frontier.lvlMode == FRONTIER_LVL_50)
gLinkType = LINKTYPE_BATTLE_TOWER_50;
2018-10-13 19:41:10 +02:00
else
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BATTLE_TOWER_OPEN;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_TRADE_CENTER:
2020-06-04 00:00:53 +02:00
gLinkType = LINKTYPE_TRADE;
2018-10-13 19:41:10 +02:00
break;
2019-10-11 10:14:09 +02:00
case USING_RECORD_CORNER:
2020-06-04 00:00:53 +02:00
gLinkType = LINKTYPE_RECORD_MIX_AFTER;
2018-10-13 19:41:10 +02:00
break;
}
2020-06-04 00:00:53 +02:00
return CreateTask(Task_ReestablishLink, 80);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
static void Task_ReestablishLink(u8 taskId)
2018-10-13 19:41:10 +02:00
{
s16 *data = gTasks[taskId].data;
if (data[0] == 0)
{
OpenLink();
ResetLinkPlayers();
2020-06-04 00:00:53 +02:00
CreateTask(Task_WaitForLinkPlayerConnection, 80);
2018-10-13 19:41:10 +02:00
}
else if (data[0] >= 10)
{
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_ReestablishLinkAwaitConnection;
2018-10-13 19:41:10 +02:00
}
data[0]++;
}
2020-06-04 00:00:53 +02:00
static void Task_ReestablishLinkAwaitConnection(u8 taskId)
2018-10-13 19:41:10 +02:00
{
if (GetLinkPlayerCount_2() >= 2)
{
if (IsLinkMaster() == TRUE)
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_ReestablishLinkLeader;
2018-10-13 19:41:10 +02:00
else
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_ReestablishLinkAwaitConfirmation;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_ReestablishLinkLeader(u8 taskId)
2018-10-13 19:41:10 +02:00
{
if (GetSavedPlayerCount() == GetLinkPlayerCount_2())
2018-10-13 19:41:10 +02:00
{
CheckShouldAdvanceLinkState();
2020-06-04 00:00:53 +02:00
gTasks[taskId].func = Task_ReestablishLinkAwaitConfirmation;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
static void Task_ReestablishLinkAwaitConfirmation(u8 taskId)
2018-10-13 19:41:10 +02:00
{
if (gReceivedRemoteLinkPlayers == TRUE
&& IsLinkPlayerDataExchangeComplete() == TRUE)
{
CheckLinkPlayersMatchSaved();
StartSendingKeysToLink();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
}
// Unused
void CableClubSaveGame(void)
2018-10-13 19:41:10 +02:00
{
SaveGame();
}
2019-10-11 10:14:09 +02:00
static void SetLinkBattleTypeFlags(int linkService)
2018-10-13 19:41:10 +02:00
{
2019-10-11 10:14:09 +02:00
switch (linkService)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
case USING_SINGLE_BATTLE:
gBattleTypeFlags = BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER;
break;
case USING_DOUBLE_BATTLE:
gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER;
break;
case USING_MULTI_BATTLE:
ReducePlayerPartyToSelectedMons();
gBattleTypeFlags = BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER | BATTLE_TYPE_MULTI;
break;
case USING_BATTLE_TOWER:
gBattleTypeFlags = BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER | BATTLE_TYPE_MULTI;
break;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
#define tTimer data[1]
static void Task_StartWiredCableClubBattle(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2022-07-29 17:15:33 +02:00
struct Task *task = &gTasks[taskId];
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
switch (task->tState)
2018-10-13 19:41:10 +02:00
{
case 0:
2019-12-15 17:42:50 +01:00
FadeScreen(FADE_TO_BLACK, 0);
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BATTLE;
2018-10-13 19:41:10 +02:00
ClearLinkCallback_2();
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 1:
if (!gPaletteFade.active)
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 2:
2020-06-04 00:00:53 +02:00
task->tTimer++;
if (task->tTimer > 20)
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 3:
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 4:
if (!gReceivedRemoteLinkPlayers)
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 5:
if (gLinkPlayers[0].trainerId & 1)
2020-08-21 00:02:00 +02:00
PlayMapChosenOrBattleBGM(MUS_VS_GYM_LEADER);
2018-10-13 19:41:10 +02:00
else
2020-08-21 00:02:00 +02:00
PlayMapChosenOrBattleBGM(MUS_VS_TRAINER);
2018-10-13 19:41:10 +02:00
2019-10-11 10:14:09 +02:00
SetLinkBattleTypeFlags(gSpecialVar_0x8004);
2018-12-27 23:30:47 +01:00
CleanupOverworldWindowsAndTilemaps();
2020-06-04 00:00:53 +02:00
gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT;
2018-10-13 19:41:10 +02:00
SetMainCallback2(CB2_InitBattle);
2020-05-30 10:09:21 +02:00
gMain.savedCallback = CB2_ReturnFromCableClubBattle;
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
break;
}
}
2020-06-04 00:00:53 +02:00
static void Task_StartWirelessCableClubBattle(u8 taskId)
2018-10-13 19:41:10 +02:00
{
int i;
s16 *data = gTasks[taskId].data;
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
switch (tState)
2018-10-13 19:41:10 +02:00
{
case 0:
2019-12-15 17:42:50 +01:00
FadeScreen(FADE_TO_BLACK, 0);
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BATTLE;
2018-10-13 19:41:10 +02:00
ClearLinkCallback_2();
2020-06-04 00:00:53 +02:00
tState = 1;
2018-10-13 19:41:10 +02:00
break;
case 1:
if (!gPaletteFade.active)
2020-06-04 00:00:53 +02:00
tState = 2;
2018-10-13 19:41:10 +02:00
break;
case 2:
SendBlock(0, &gLocalLinkPlayer, sizeof(gLocalLinkPlayer));
2020-06-04 00:00:53 +02:00
tState = 3;
2018-10-13 19:41:10 +02:00
break;
case 3:
if (GetBlockReceivedStatus() == GetLinkPlayerCountAsBitFlags())
2018-10-13 19:41:10 +02:00
{
for (i = 0; i < GetLinkPlayerCount(); i++)
{
struct LinkPlayer *player = (struct LinkPlayer *)gBlockRecvBuffer[i];
gLinkPlayers[i] = *player;
2021-03-19 19:10:13 +01:00
ConvertLinkPlayerName(&gLinkPlayers[i]);
2018-10-13 19:41:10 +02:00
ResetBlockReceivedFlag(i);
}
2020-06-04 00:00:53 +02:00
tState = 4;
2018-10-13 19:41:10 +02:00
}
break;
case 4:
2020-06-04 00:00:53 +02:00
tTimer++;
if (tTimer > 20)
tState = 5;
2018-10-13 19:41:10 +02:00
break;
case 5:
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-06-04 00:00:53 +02:00
tState = 6;
2018-10-13 19:41:10 +02:00
break;
case 6:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
tState = 7;
2018-10-13 19:41:10 +02:00
}
break;
case 7:
if (gLinkPlayers[0].trainerId & 1)
2020-08-21 00:02:00 +02:00
PlayMapChosenOrBattleBGM(MUS_VS_GYM_LEADER);
2018-10-13 19:41:10 +02:00
else
2020-08-21 00:02:00 +02:00
PlayMapChosenOrBattleBGM(MUS_VS_TRAINER);
2018-10-13 19:41:10 +02:00
2019-10-11 10:14:09 +02:00
gLinkPlayers[0].linkType = LINKTYPE_BATTLE;
SetLinkBattleTypeFlags(gSpecialVar_0x8004);
2018-12-27 23:30:47 +01:00
CleanupOverworldWindowsAndTilemaps();
2020-06-04 00:00:53 +02:00
gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT;
2018-10-13 19:41:10 +02:00
SetMainCallback2(CB2_InitBattle);
2020-05-30 10:09:21 +02:00
gMain.savedCallback = CB2_ReturnFromCableClubBattle;
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
break;
}
}
2020-06-04 00:00:53 +02:00
#undef tTimer
static void CB2_ReturnFromUnionRoomBattle(void)
2018-10-13 19:41:10 +02:00
{
u8 playerCount;
int i;
2020-06-04 00:00:53 +02:00
bool32 linkedWithFRLG;
2018-10-13 19:41:10 +02:00
switch (gMain.state)
{
2020-06-04 00:00:53 +02:00
case 0:
playerCount = GetLinkPlayerCount();
linkedWithFRLG = FALSE;
for (i = 0; i < playerCount; i++)
{
u32 version = (u8)gLinkPlayers[i].version;
if (version == VERSION_FIRE_RED || version == VERSION_LEAF_GREEN)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
linkedWithFRLG = TRUE;
break;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
}
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
if (linkedWithFRLG)
{
gMain.state = 2;
}
else
{
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2020-06-04 00:00:53 +02:00
gMain.state = 1;
}
break;
case 1:
if (!gReceivedRemoteLinkPlayers)
{
2018-10-13 19:41:10 +02:00
SetMainCallback2(CB2_ReturnToField);
2020-06-04 00:00:53 +02:00
}
break;
case 2:
SetMainCallback2(CB2_ReturnToField);
break;
2018-10-13 19:41:10 +02:00
}
RunTasks();
}
2020-05-30 10:09:21 +02:00
void CB2_ReturnFromCableClubBattle(void)
2018-10-13 19:41:10 +02:00
{
2021-01-13 21:17:32 +01:00
gBattleTypeFlags &= ~BATTLE_TYPE_LINK_IN_BATTLE;
2018-10-13 19:41:10 +02:00
Overworld_ResetMapMusic();
LoadPlayerParty();
SavePlayerBag();
2019-11-17 23:34:11 +01:00
UpdateTrainerFansAfterLinkBattle();
2018-10-13 19:41:10 +02:00
2019-10-11 10:14:09 +02:00
if (gSpecialVar_0x8004 == USING_SINGLE_BATTLE || gSpecialVar_0x8004 == USING_DOUBLE_BATTLE)
2018-10-13 19:41:10 +02:00
{
2019-02-27 04:04:44 +01:00
UpdatePlayerLinkBattleRecords(gLocalLinkPlayerId ^ 1);
2018-10-13 19:41:10 +02:00
if (gWirelessCommType)
{
switch (gBattleOutcome)
{
2020-06-04 00:00:53 +02:00
case B_OUTCOME_WON:
2021-10-17 07:35:26 +02:00
MysteryGift_TryIncrementStat(CARD_STAT_BATTLES_WON, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
2020-06-04 00:00:53 +02:00
break;
case B_OUTCOME_LOST:
2021-10-17 07:35:26 +02:00
MysteryGift_TryIncrementStat(CARD_STAT_BATTLES_LOST, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
2020-06-04 00:00:53 +02:00
break;
2018-10-13 19:41:10 +02:00
}
}
}
if (InUnionRoom() == TRUE)
2020-06-04 00:00:53 +02:00
gMain.savedCallback = CB2_ReturnFromUnionRoomBattle;
2018-10-13 19:41:10 +02:00
else
gMain.savedCallback = CB2_ReturnToFieldFromMultiplayer;
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
SetMainCallback2(CB2_SetUpSaveAfterLinkBattle);
2018-10-13 19:41:10 +02:00
}
2019-02-18 07:03:44 +01:00
void CleanupLinkRoomState(void)
2018-10-13 19:41:10 +02:00
{
if (gSpecialVar_0x8004 == USING_SINGLE_BATTLE
|| gSpecialVar_0x8004 == USING_DOUBLE_BATTLE
|| gSpecialVar_0x8004 == USING_MULTI_BATTLE
2019-10-11 10:14:09 +02:00
|| gSpecialVar_0x8004 == USING_BATTLE_TOWER)
2018-10-13 19:41:10 +02:00
{
LoadPlayerParty();
SavePlayerBag();
}
SetWarpDestinationToDynamicWarp(WARP_ID_DYNAMIC);
2018-10-13 19:41:10 +02:00
}
2019-02-18 07:03:44 +01:00
void ExitLinkRoom(void)
2018-10-13 19:41:10 +02:00
{
QueueExitLinkRoomKey();
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
// Note: gSpecialVar_0x8005 contains the id of the seat the player entered
static void Task_EnterCableClubSeat(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2022-07-29 17:15:33 +02:00
struct Task *task = &gTasks[taskId];
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
switch (task->tState)
2018-10-13 19:41:10 +02:00
{
case 0:
ShowFieldMessage(gText_PleaseWaitForLink);
2020-06-04 00:00:53 +02:00
task->tState = 1;
2018-10-13 19:41:10 +02:00
break;
case 1:
if (IsFieldMessageBoxHidden())
{
2021-04-06 22:55:33 +02:00
SetInCableClubSeat();
2019-03-01 07:18:58 +01:00
SetLocalLinkPlayerId(gSpecialVar_0x8005);
2020-06-04 00:00:53 +02:00
task->tState = 2;
2018-10-13 19:41:10 +02:00
}
break;
case 2:
2021-04-06 22:55:33 +02:00
switch (GetCableClubPartnersReady())
2018-10-13 19:41:10 +02:00
{
2021-04-06 22:55:33 +02:00
case CABLE_SEAT_WAITING:
2018-10-13 19:41:10 +02:00
break;
2021-04-06 22:55:33 +02:00
case CABLE_SEAT_SUCCESS:
// Partners linked and ready, switch to relevant link function
2018-10-13 19:41:10 +02:00
HideFieldMessageBox();
2020-06-04 00:00:53 +02:00
task->tState = 0;
2021-04-06 22:55:33 +02:00
SetStartedCableClubActivity();
2018-10-13 19:41:10 +02:00
SwitchTaskToFollowupFunc(taskId);
break;
2021-04-06 22:55:33 +02:00
case CABLE_SEAT_FAILED:
2020-06-04 00:00:53 +02:00
task->tState = 3;
2018-10-13 19:41:10 +02:00
break;
}
break;
case 3:
2021-04-06 22:55:33 +02:00
// Exit, failure
SetLinkWaitingForScript();
2021-11-03 21:06:58 +01:00
EraseFieldMessageBox(TRUE);
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
break;
}
}
2020-06-04 00:00:53 +02:00
void CreateTask_EnterCableClubSeat(TaskFunc followupFunc)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
u8 taskId = CreateTask(Task_EnterCableClubSeat, 80);
SetTaskFuncWithFollowupFunc(taskId, Task_EnterCableClubSeat, followupFunc);
ScriptContext_Stop();
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
static void Task_StartWiredTrade(u8 taskId)
2018-10-13 19:41:10 +02:00
{
struct Task *task = &gTasks[taskId];
2020-06-04 00:00:53 +02:00
switch (task->tState)
2018-10-13 19:41:10 +02:00
{
case 0:
LockPlayerFieldControls();
2019-12-15 17:42:50 +01:00
FadeScreen(FADE_TO_BLACK, 0);
2018-10-13 19:41:10 +02:00
ClearLinkCallback_2();
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 1:
if (!gPaletteFade.active)
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 2:
2019-10-04 01:39:37 +02:00
gSelectedTradeMonPositions[TRADE_PLAYER] = 0;
gSelectedTradeMonPositions[TRADE_PARTNER] = 0;
2018-10-13 19:41:10 +02:00
m4aMPlayAllStop();
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2020-06-04 00:00:53 +02:00
task->tState++;
2018-10-13 19:41:10 +02:00
break;
case 3:
if (!gReceivedRemoteLinkPlayers)
{
2019-10-09 11:56:44 +02:00
SetMainCallback2(CB2_StartCreateTradeMenu);
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
break;
}
}
2020-06-04 00:00:53 +02:00
static void Task_StartWirelessTrade(u8 taskId)
2018-10-13 19:41:10 +02:00
{
s16 *data = gTasks[taskId].data;
2020-06-04 00:00:53 +02:00
switch (tState)
2018-10-13 19:41:10 +02:00
{
case 0:
LockPlayerFieldControls();
2019-12-15 17:42:50 +01:00
FadeScreen(FADE_TO_BLACK, 0);
2019-10-05 16:41:37 +02:00
ClearLinkRfuCallback();
2020-06-04 00:00:53 +02:00
tState++;
2018-10-13 19:41:10 +02:00
break;
case 1:
if (!gPaletteFade.active)
2020-06-04 00:00:53 +02:00
tState++;
2018-10-13 19:41:10 +02:00
break;
case 2:
2019-10-04 01:39:37 +02:00
gSelectedTradeMonPositions[TRADE_PLAYER] = 0;
gSelectedTradeMonPositions[TRADE_PARTNER] = 0;
2018-10-13 19:41:10 +02:00
m4aMPlayAllStop();
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-06-04 00:00:53 +02:00
tState++;
2018-10-13 19:41:10 +02:00
break;
case 3:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
CreateTask_CreateTradeMenu();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
break;
}
}
2019-02-18 07:03:44 +01:00
void PlayerEnteredTradeSeat(void)
2018-10-13 19:41:10 +02:00
{
if (gWirelessCommType != 0)
2020-06-04 00:00:53 +02:00
CreateTask_EnterCableClubSeat(Task_StartWirelessTrade);
2018-10-13 19:41:10 +02:00
else
2020-06-04 00:00:53 +02:00
CreateTask_EnterCableClubSeat(Task_StartWiredTrade);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
// Unused
static void CreateTask_StartWiredTrade(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
CreateTask(Task_StartWiredTrade, 80);
2018-10-13 19:41:10 +02:00
}
// Unused, implemented in Ruby/Sapphire
void Script_StartWiredTrade(void)
2018-10-13 19:41:10 +02:00
{
// CreateTask_StartWiredTrade();
// ScriptContext_Stop();
2018-10-13 19:41:10 +02:00
}
2019-02-18 07:03:44 +01:00
void ColosseumPlayerSpotTriggered(void)
2018-10-13 19:41:10 +02:00
{
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BATTLE;
2018-10-13 19:41:10 +02:00
2020-06-04 00:00:53 +02:00
if (gWirelessCommType)
CreateTask_EnterCableClubSeat(Task_StartWirelessCableClubBattle);
2018-10-13 19:41:10 +02:00
else
2020-06-04 00:00:53 +02:00
CreateTask_EnterCableClubSeat(Task_StartWiredCableClubBattle);
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
// Unused
static void CreateTask_EnterCableClubSeatNoFollowup(void)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
u8 taskId = CreateTask(Task_EnterCableClubSeat, 80);
ScriptContext_Stop();
2018-10-13 19:41:10 +02:00
}
2019-10-11 10:14:09 +02:00
void Script_ShowLinkTrainerCard(void)
2018-10-13 19:41:10 +02:00
{
2019-01-20 18:24:35 +01:00
ShowTrainerCardInLink(gSpecialVar_0x8006, CB2_ReturnToFieldContinueScriptPlayMapMusic);
2018-10-13 19:41:10 +02:00
}
// Returns FALSE if the player has no stars. Returns TRUE otherwise, and puts the name of the
// color into gStringVar2.
bool32 GetLinkTrainerCardColor(u8 linkPlayerIndex)
2018-10-13 19:41:10 +02:00
{
2020-02-07 18:48:47 +01:00
u32 numStars;
2018-10-13 19:41:10 +02:00
gSpecialVar_0x8006 = linkPlayerIndex;
StringCopy(gStringVar1, gLinkPlayers[linkPlayerIndex].name);
2020-02-07 18:48:47 +01:00
numStars = GetTrainerCardStars(linkPlayerIndex);
if (numStars == 0)
2018-10-13 19:41:10 +02:00
return FALSE;
2020-06-04 00:00:53 +02:00
StringCopy(gStringVar2, sTrainerCardColorNames[numStars - 1]);
2018-10-13 19:41:10 +02:00
return TRUE;
}
2020-06-04 00:00:53 +02:00
#define tTimer data[0]
void Task_WaitForLinkPlayerConnection(u8 taskId)
2018-10-13 19:41:10 +02:00
{
struct Task *task = &gTasks[taskId];
2020-06-04 00:00:53 +02:00
task->tTimer++;
if (task->tTimer > 300)
2018-10-13 19:41:10 +02:00
{
CloseLink();
SetMainCallback2(CB2_LinkError);
DestroyTask(taskId);
}
if (gReceivedRemoteLinkPlayers)
{
2020-06-04 00:00:53 +02:00
// Players connected, destroy task
2018-10-13 19:41:10 +02:00
if (gWirelessCommType == 0)
{
if (!DoesLinkPlayerCountMatchSaved())
2018-10-13 19:41:10 +02:00
{
CloseLink();
SetMainCallback2(CB2_LinkError);
}
DestroyTask(taskId);
}
else
{
DestroyTask(taskId);
}
}
}
2020-06-04 00:00:53 +02:00
#undef tTimer
static void Task_WaitExitToScript(u8 taskId)
2018-10-13 19:41:10 +02:00
{
if (!gReceivedRemoteLinkPlayers)
{
ScriptContext_Enable();
2018-10-13 19:41:10 +02:00
DestroyTask(taskId);
}
}
2020-06-04 00:00:53 +02:00
// Unused
static void ExitLinkToScript(u8 taskId)
2018-10-13 19:41:10 +02:00
{
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
gTasks[taskId].func = Task_WaitExitToScript;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
#define tTimer data[1]
2021-03-04 23:48:40 +01:00
// Confirm that all cabled link players are connected
void Task_ReconnectWithLinkPlayers(u8 taskId)
2018-10-13 19:41:10 +02:00
{
s16 *data = gTasks[taskId].data;
2020-06-04 00:00:53 +02:00
switch (tState)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
case 0:
if (gWirelessCommType != 0)
{
DestroyTask(taskId);
}
else
{
OpenLink();
CreateTask(Task_WaitForLinkPlayerConnection, 1);
tState++;
}
break;
case 1:
if (++tTimer > 11)
{
tTimer = 0;
tState++;
}
break;
case 2:
if (GetLinkPlayerCount_2() >= GetSavedPlayerCount())
{
if (IsLinkMaster())
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
if (++tTimer > 30)
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
CheckShouldAdvanceLinkState();
tState++;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
else
2018-10-13 19:41:10 +02:00
{
2020-06-04 00:00:53 +02:00
tState++;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
}
break;
case 3:
if (gReceivedRemoteLinkPlayers == TRUE && IsLinkPlayerDataExchangeComplete() == TRUE)
{
DestroyTask(taskId);
}
break;
2018-10-13 19:41:10 +02:00
}
}
2020-06-04 00:00:53 +02:00
#undef tTimer
void TrySetBattleTowerLinkType(void)
2018-10-13 19:41:10 +02:00
{
if (gWirelessCommType == 0)
gLinkType = LINKTYPE_BATTLE_TOWER;
2018-10-13 19:41:10 +02:00
}
2020-06-04 00:00:53 +02:00
#undef tState