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