Merge branch 'master' into sync-text
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@
|
||||
#include "link.h"
|
||||
#include "load_save.h"
|
||||
#include "m4a.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "overworld.h"
|
||||
#include "quest_log.h"
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@
|
||||
#include "easy_chat.h"
|
||||
#include "event_data.h"
|
||||
#include "field_message_box.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "menu.h"
|
||||
#include "mail.h"
|
||||
#include "pokedex.h"
|
||||
@@ -472,11 +472,11 @@ void InitEasyChatPhrases(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void EC_ResetMEventProfileMaybe(void)
|
||||
void InitQuestionnaireWords(void)
|
||||
{
|
||||
s32 i;
|
||||
u16 *ptr = GetMEventProfileECWordsMaybe();
|
||||
for (i = 0; i < 4; i++)
|
||||
u16 *ptr = GetQuestionnaireWordsPtr();
|
||||
for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
|
||||
ptr[i] = EC_WORD_UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
#include "easy_chat.h"
|
||||
#include "event_data.h"
|
||||
#include "menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "overworld.h"
|
||||
#include "strings.h"
|
||||
#include "task.h"
|
||||
@@ -271,7 +271,7 @@ void ShowEasyChatScreen(void)
|
||||
words = gSaveBlock1Ptr->easyChatBattleLost;
|
||||
break;
|
||||
case EASY_CHAT_TYPE_QUESTIONNAIRE:
|
||||
words = GetMEventProfileECWordsMaybe();
|
||||
words = GetQuestionnaireWordsPtr();
|
||||
break;
|
||||
case EASY_CHAT_TYPE_MAIL:
|
||||
words = gSaveBlock1Ptr->mail[gSpecialVar_0x8005].words;
|
||||
|
||||
@@ -0,0 +1,520 @@
|
||||
#include "global.h"
|
||||
#include "malloc.h"
|
||||
#include "decompress.h"
|
||||
#include "ereader_helpers.h"
|
||||
#include "link.h"
|
||||
#include "main.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "save.h"
|
||||
#include "sound.h"
|
||||
#include "sprite.h"
|
||||
#include "task.h"
|
||||
#include "strings.h"
|
||||
#include "util.h"
|
||||
#include "cereader_tool.h"
|
||||
#include "help_system.h"
|
||||
#include "constants/songs.h"
|
||||
|
||||
struct EReaderTaskData
|
||||
{
|
||||
u16 timer;
|
||||
u16 unused1;
|
||||
u16 unused2;
|
||||
u16 unused3;
|
||||
u8 state;
|
||||
u8 textState;
|
||||
u8 unused4;
|
||||
u8 unused5;
|
||||
u8 unused6;
|
||||
u8 unused7;
|
||||
u8 status;
|
||||
u8 *unusedBuffer;
|
||||
};
|
||||
|
||||
struct EReaderData
|
||||
{
|
||||
u16 status;
|
||||
size_t size;
|
||||
const void *data;
|
||||
};
|
||||
|
||||
static void Task_EReader(u8);
|
||||
|
||||
struct EReaderData gEReaderData;
|
||||
|
||||
extern const u8 gMultiBootProgram_EReader_Start[];
|
||||
extern const u8 gMultiBootProgram_EReader_End[];
|
||||
|
||||
static void EReader_Load(struct EReaderData *eReader, size_t size, const void *data)
|
||||
{
|
||||
vu16 imeBak = REG_IME;
|
||||
REG_IME = 0;
|
||||
gIntrTable[1] = EReaderHelper_SerialCallback;
|
||||
gIntrTable[2] = EReaderHelper_Timer3Callback;
|
||||
EReaderHelper_SaveRegsState();
|
||||
EReaderHelper_ClearsSendRecvMgr();
|
||||
REG_IE |= INTR_FLAG_VCOUNT;
|
||||
REG_IME = imeBak;
|
||||
eReader->status = 0;
|
||||
eReader->size = size;
|
||||
eReader->data = data;
|
||||
}
|
||||
|
||||
static void EReader_Reset(struct EReaderData *eReader)
|
||||
{
|
||||
vu16 imeBak = REG_IME;
|
||||
REG_IME = 0;
|
||||
EReaderHelper_ClearsSendRecvMgr();
|
||||
EReaderHelper_RestoreRegsState();
|
||||
RestoreSerialTimer3IntrHandlers();
|
||||
REG_IME = imeBak;
|
||||
}
|
||||
|
||||
// Return values for EReader_Transfer
|
||||
enum {
|
||||
TRANSFER_ACTIVE,
|
||||
TRANSFER_SUCCESS,
|
||||
TRANSFER_CANCELED,
|
||||
TRANSFER_TIMEOUT,
|
||||
};
|
||||
|
||||
static u8 EReader_Transfer(struct EReaderData *eReader)
|
||||
{
|
||||
u8 transferStatus = TRANSFER_ACTIVE;
|
||||
eReader->status = EReaderHandleTransfer(TRUE, eReader->size, eReader->data, NULL);
|
||||
|
||||
if ((eReader->status & EREADER_XFER_MASK) == 0 && eReader->status & EREADER_CHECKSUM_OK_MASK)
|
||||
transferStatus = TRANSFER_SUCCESS;
|
||||
|
||||
if (eReader->status & EREADER_CANCEL_KEY_MASK)
|
||||
transferStatus = TRANSFER_CANCELED;
|
||||
|
||||
if (eReader->status & EREADER_CANCEL_TIMEOUT_MASK)
|
||||
transferStatus = TRANSFER_TIMEOUT;
|
||||
|
||||
gShouldAdvanceLinkState = 0;
|
||||
return transferStatus;
|
||||
}
|
||||
|
||||
static void OpenEReaderLink(void)
|
||||
{
|
||||
memset(gDecompressionBuffer, 0, 0x2000);
|
||||
gLinkType = LINKTYPE_EREADER_FRLG;
|
||||
OpenLink();
|
||||
SetSuppressLinkErrorMessage(TRUE);
|
||||
}
|
||||
|
||||
static bool32 ValidateEReaderConnection(void)
|
||||
{
|
||||
vu16 imeBak = REG_IME;
|
||||
u16 handshakes[MAX_LINK_PLAYERS];
|
||||
|
||||
REG_IME = 0;
|
||||
*(u64 *)handshakes = *(u64 *)gLink.tempRecvBuffer;
|
||||
REG_IME = imeBak;
|
||||
|
||||
// Validate that we are player 1, the EReader is player 2,
|
||||
// and that players 3 and 4 are empty.
|
||||
if (handshakes[0] == SLAVE_HANDSHAKE
|
||||
&& handshakes[1] == EREADER_HANDSHAKE
|
||||
&& handshakes[2] == 0xFFFF
|
||||
&& handshakes[3] == 0xFFFF)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 IsEReaderConnectionSane(void)
|
||||
{
|
||||
if (IsLinkMaster() && GetLinkPlayerCount_2() == 2)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// States for TryReceiveCard
|
||||
enum {
|
||||
RECV_STATE_INIT,
|
||||
RECV_STATE_WAIT_START,
|
||||
RECV_STATE_START,
|
||||
RECV_STATE_EXCHANGE,
|
||||
RECV_STATE_START_DISCONNECT,
|
||||
RECV_STATE_WAIT_DISCONNECT,
|
||||
};
|
||||
|
||||
// Return values for TryReceiveCard
|
||||
enum {
|
||||
RECV_ACTIVE,
|
||||
RECV_CANCELED,
|
||||
RECV_SUCCESS,
|
||||
RECV_ERROR,
|
||||
RECV_DISCONNECTED,
|
||||
RECV_TIMEOUT,
|
||||
};
|
||||
|
||||
static u32 TryReceiveCard(u8 * state, u16 * timer)
|
||||
{
|
||||
if ((*state == RECV_STATE_EXCHANGE
|
||||
|| *state == RECV_STATE_START_DISCONNECT
|
||||
|| *state == RECV_STATE_WAIT_DISCONNECT)
|
||||
&& HasLinkErrorOccurred())
|
||||
{
|
||||
// Return error status if an error occurs
|
||||
// during the link exchange.
|
||||
*state = 0;
|
||||
return RECV_ERROR;
|
||||
}
|
||||
|
||||
switch (*state)
|
||||
{
|
||||
case RECV_STATE_INIT:
|
||||
if (IsLinkMaster() && GetLinkPlayerCount_2() > 1)
|
||||
{
|
||||
*state = RECV_STATE_WAIT_START;
|
||||
}
|
||||
else if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
*state = 0;
|
||||
return RECV_CANCELED;
|
||||
}
|
||||
break;
|
||||
case RECV_STATE_WAIT_START:
|
||||
if (++(*timer) > 5)
|
||||
{
|
||||
*timer = 0;
|
||||
*state = RECV_STATE_START;
|
||||
}
|
||||
break;
|
||||
case RECV_STATE_START:
|
||||
if (GetLinkPlayerCount_2() == 2)
|
||||
{
|
||||
PlaySE(SE_DING_DONG);
|
||||
CheckShouldAdvanceLinkState();
|
||||
*timer = 0;
|
||||
*state = RECV_STATE_EXCHANGE;
|
||||
}
|
||||
else if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
*state = 0;
|
||||
return RECV_CANCELED;
|
||||
}
|
||||
break;
|
||||
case RECV_STATE_EXCHANGE:
|
||||
if (++(*timer) > 30)
|
||||
{
|
||||
*state = 0;
|
||||
return RECV_TIMEOUT;
|
||||
}
|
||||
|
||||
if (IsLinkConnectionEstablished())
|
||||
{
|
||||
if (gReceivedRemoteLinkPlayers)
|
||||
{
|
||||
if (IsLinkPlayerDataExchangeComplete())
|
||||
{
|
||||
*state = 0;
|
||||
return RECV_SUCCESS;
|
||||
}
|
||||
else
|
||||
*state = RECV_STATE_START_DISCONNECT;
|
||||
}
|
||||
else
|
||||
*state = RECV_STATE_EXCHANGE;
|
||||
}
|
||||
break;
|
||||
case RECV_STATE_START_DISCONNECT:
|
||||
SetCloseLinkCallbackAndType(0);
|
||||
*state = RECV_STATE_WAIT_DISCONNECT;
|
||||
break;
|
||||
case RECV_STATE_WAIT_DISCONNECT:
|
||||
if (!gReceivedRemoteLinkPlayers)
|
||||
{
|
||||
*state = 0;
|
||||
return RECV_DISCONNECTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return RECV_ACTIVE;
|
||||
}
|
||||
|
||||
void CreateEReaderTask(void)
|
||||
{
|
||||
u8 taskId = CreateTask(Task_EReader, 0);
|
||||
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
|
||||
data->state = 0;
|
||||
data->textState = 0;
|
||||
data->unused4 = 0;
|
||||
data->unused5 = 0;
|
||||
data->unused6 = 0;
|
||||
data->unused7 = 0;
|
||||
data->timer = 0;
|
||||
data->unused1 = 0;
|
||||
data->unused2 = 0;
|
||||
data->unused3 = 0;
|
||||
data->status = 0;
|
||||
data->unusedBuffer = AllocZeroed(CLIENT_MAX_MSG_SIZE);
|
||||
}
|
||||
|
||||
static void ResetTimer(u16 *timer)
|
||||
{
|
||||
*timer = 0;
|
||||
}
|
||||
|
||||
static bool32 UpdateTimer(u16 * timer, u16 time)
|
||||
{
|
||||
if (++(*timer) > time)
|
||||
{
|
||||
// Timer has finished
|
||||
*timer = 0;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// States for Task_EReader
|
||||
enum {
|
||||
ER_STATE_START,
|
||||
ER_STATE_INIT_LINK,
|
||||
ER_STATE_INIT_LINK_WAIT,
|
||||
ER_STATE_INIT_LINK_CHECK,
|
||||
ER_STATE_MSG_SELECT_CONNECT,
|
||||
ER_STATE_MSG_SELECT_CONNECT_WAIT,
|
||||
ER_STATE_TRY_LINK,
|
||||
ER_STATE_INCORRECT_LINK,
|
||||
ER_STATE_CONNECTING,
|
||||
ER_STATE_TRANSFER,
|
||||
ER_STATE_TRANSFER_END,
|
||||
ER_STATE_TRANSFER_SUCCESS,
|
||||
ER_STATE_LOAD_CARD_START,
|
||||
ER_STATE_LOAD_CARD,
|
||||
ER_STATE_WAIT_RECV_CARD,
|
||||
ER_STATE_VALIDATE_CARD,
|
||||
ER_STATE_WAIT_DISCONNECT,
|
||||
ER_STATE_SAVE,
|
||||
ER_STATE_SUCCESS_MSG,
|
||||
ER_STATE_SUCCESS_END,
|
||||
ER_STATE_LINK_ERROR,
|
||||
ER_STATE_LINK_ERROR_TRY_AGAIN,
|
||||
ER_STATE_SAVE_FAILED,
|
||||
ER_STATE_CANCELED_CARD_READ,
|
||||
ER_STATE_UNUSED_1,
|
||||
ER_STATE_UNUSED_2,
|
||||
ER_STATE_END,
|
||||
};
|
||||
|
||||
static void Task_EReader(u8 taskId)
|
||||
{
|
||||
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
|
||||
switch (data->state)
|
||||
{
|
||||
case ER_STATE_START:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ReceiveMysteryGiftWithEReader))
|
||||
data->state = ER_STATE_INIT_LINK;
|
||||
break;
|
||||
case ER_STATE_INIT_LINK:
|
||||
OpenEReaderLink();
|
||||
ResetTimer(&data->timer);
|
||||
data->state = ER_STATE_INIT_LINK_WAIT;
|
||||
break;
|
||||
case ER_STATE_INIT_LINK_WAIT:
|
||||
if (UpdateTimer(&data->timer, 10))
|
||||
data->state = ER_STATE_INIT_LINK_CHECK;
|
||||
break;
|
||||
case ER_STATE_INIT_LINK_CHECK:
|
||||
if (!IsEReaderConnectionSane())
|
||||
{
|
||||
CloseLink();
|
||||
data->state = ER_STATE_MSG_SELECT_CONNECT;
|
||||
}
|
||||
else
|
||||
data->state = ER_STATE_LOAD_CARD;
|
||||
break;
|
||||
case ER_STATE_MSG_SELECT_CONNECT:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_SelectConnectFromEReaderMenu))
|
||||
{
|
||||
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
|
||||
ResetTimer(&data->timer);
|
||||
data->state = ER_STATE_MSG_SELECT_CONNECT_WAIT;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_MSG_SELECT_CONNECT_WAIT:
|
||||
if (UpdateTimer(&data->timer, 90))
|
||||
{
|
||||
OpenEReaderLink();
|
||||
data->state = ER_STATE_TRY_LINK;
|
||||
}
|
||||
else if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
ResetTimer(&data->timer);
|
||||
PlaySE(SE_SELECT);
|
||||
data->state = ER_STATE_CANCELED_CARD_READ;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_TRY_LINK:
|
||||
if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
// Canceled
|
||||
PlaySE(SE_SELECT);
|
||||
CloseLink();
|
||||
ResetTimer(&data->timer);
|
||||
data->state = ER_STATE_CANCELED_CARD_READ;
|
||||
}
|
||||
else if (GetLinkPlayerCount_2() > 1)
|
||||
{
|
||||
ResetTimer(&data->timer);
|
||||
CloseLink();
|
||||
data->state = ER_STATE_INCORRECT_LINK;
|
||||
}
|
||||
else if (ValidateEReaderConnection())
|
||||
{
|
||||
// Successful connection
|
||||
PlaySE(SE_SELECT);
|
||||
CloseLink();
|
||||
ResetTimer(&data->timer);
|
||||
data->state = ER_STATE_CONNECTING;
|
||||
}
|
||||
else if (UpdateTimer(&data->timer, 10))
|
||||
{
|
||||
// Retry connection
|
||||
CloseLink();
|
||||
OpenEReaderLink();
|
||||
ResetTimer(&data->timer);
|
||||
}
|
||||
break;
|
||||
case ER_STATE_INCORRECT_LINK:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_LinkIsIncorrect))
|
||||
data->state = ER_STATE_MSG_SELECT_CONNECT;
|
||||
break;
|
||||
case ER_STATE_CONNECTING:
|
||||
AddTextPrinterToWindow1(gJPText_Connecting);
|
||||
EReader_Load(&gEReaderData, gMultiBootProgram_EReader_End - gMultiBootProgram_EReader_Start, gMultiBootProgram_EReader_Start);
|
||||
data->state = ER_STATE_TRANSFER;
|
||||
break;
|
||||
case ER_STATE_TRANSFER:
|
||||
data->status = EReader_Transfer(&gEReaderData);
|
||||
if (data->status != TRANSFER_ACTIVE)
|
||||
data->state = ER_STATE_TRANSFER_END;
|
||||
break;
|
||||
case ER_STATE_TRANSFER_END:
|
||||
EReader_Reset(&gEReaderData);
|
||||
if (data->status == TRANSFER_TIMEOUT)
|
||||
{
|
||||
data->state = ER_STATE_LINK_ERROR;
|
||||
}
|
||||
else if (data->status == TRANSFER_SUCCESS)
|
||||
{
|
||||
ResetTimer(&data->timer);
|
||||
AddTextPrinterToWindow1(gJPText_PleaseWaitAMoment);
|
||||
data->state = ER_STATE_TRANSFER_SUCCESS;
|
||||
}
|
||||
else // TRANSFER_CANCELED
|
||||
{
|
||||
data->state = ER_STATE_START;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_TRANSFER_SUCCESS:
|
||||
if (UpdateTimer(&data->timer, 840))
|
||||
data->state = ER_STATE_LOAD_CARD_START;
|
||||
break;
|
||||
case ER_STATE_LOAD_CARD_START:
|
||||
OpenEReaderLink();
|
||||
AddTextPrinterToWindow1(gJPText_AllowEReaderToLoadCard);
|
||||
data->state = ER_STATE_LOAD_CARD;
|
||||
break;
|
||||
case ER_STATE_LOAD_CARD:
|
||||
switch (TryReceiveCard(&data->textState, &data->timer))
|
||||
{
|
||||
case RECV_ACTIVE:
|
||||
// Running
|
||||
break;
|
||||
case RECV_SUCCESS:
|
||||
AddTextPrinterToWindow1(gJPText_Connecting);
|
||||
data->state = ER_STATE_WAIT_RECV_CARD;
|
||||
break;
|
||||
case RECV_CANCELED:
|
||||
PlaySE(SE_SELECT);
|
||||
CloseLink();
|
||||
data->state = ER_STATE_CANCELED_CARD_READ;
|
||||
break;
|
||||
case RECV_TIMEOUT:
|
||||
CloseLink();
|
||||
data->state = ER_STATE_LINK_ERROR_TRY_AGAIN;
|
||||
break;
|
||||
case RECV_ERROR:
|
||||
case RECV_DISCONNECTED:
|
||||
CloseLink();
|
||||
data->state = ER_STATE_LINK_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_WAIT_RECV_CARD:
|
||||
if (HasLinkErrorOccurred())
|
||||
{
|
||||
CloseLink();
|
||||
data->state = ER_STATE_LINK_ERROR;
|
||||
}
|
||||
else if (GetBlockReceivedStatus())
|
||||
{
|
||||
ResetBlockReceivedFlags();
|
||||
data->state = ER_STATE_VALIDATE_CARD;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_VALIDATE_CARD:
|
||||
data->status = ValidateTrainerTowerData((struct EReaderTrainerTowerSet *)gDecompressionBuffer);
|
||||
SetCloseLinkCallbackAndType(data->status);
|
||||
data->state = ER_STATE_WAIT_DISCONNECT;
|
||||
break;
|
||||
case ER_STATE_WAIT_DISCONNECT:
|
||||
if (!gReceivedRemoteLinkPlayers)
|
||||
{
|
||||
if (data->status == TRUE) // Was data valid?
|
||||
data->state = ER_STATE_SAVE;
|
||||
else
|
||||
data->state = ER_STATE_LINK_ERROR;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_SAVE:
|
||||
if (CEReaderTool_SaveTrainerTower((struct EReaderTrainerTowerSet *)gDecompressionBuffer))
|
||||
{
|
||||
AddTextPrinterToWindow1(gJPText_ConnectionComplete);
|
||||
ResetTimer(&data->timer);
|
||||
data->state = ER_STATE_SUCCESS_MSG;
|
||||
}
|
||||
else
|
||||
data->state = ER_STATE_SAVE_FAILED;
|
||||
break;
|
||||
case ER_STATE_SUCCESS_MSG:
|
||||
if (UpdateTimer(&data->timer, 120))
|
||||
{
|
||||
AddTextPrinterToWindow1(gJPText_NewTrainerHasComeToSevii);
|
||||
PlayFanfare(MUS_OBTAIN_ITEM);
|
||||
data->state = ER_STATE_SUCCESS_END;
|
||||
}
|
||||
break;
|
||||
case ER_STATE_SUCCESS_END:
|
||||
if (IsFanfareTaskInactive() && JOY_NEW(A_BUTTON | B_BUTTON))
|
||||
data->state = ER_STATE_END;
|
||||
break;
|
||||
case ER_STATE_CANCELED_CARD_READ:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_CardReadingHasBeenHalted))
|
||||
data->state = ER_STATE_END;
|
||||
break;
|
||||
case ER_STATE_LINK_ERROR:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorCheckLink))
|
||||
data->state = ER_STATE_START;
|
||||
break;
|
||||
case ER_STATE_LINK_ERROR_TRY_AGAIN:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorTryAgain))
|
||||
data->state = ER_STATE_START;
|
||||
break;
|
||||
case ER_STATE_SAVE_FAILED:
|
||||
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_WriteErrorUnableToSaveData))
|
||||
data->state = ER_STATE_START;
|
||||
break;
|
||||
case ER_STATE_END:
|
||||
HelpSystem_Enable();
|
||||
Free(data->unusedBuffer);
|
||||
DestroyTask(taskId);
|
||||
SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -129,7 +129,7 @@ bool32 IsMysteryGiftEnabled(void)
|
||||
return FlagGet(FLAG_SYS_MYSTERY_GIFT_ENABLED);
|
||||
}
|
||||
|
||||
void ResetMysteryEventFlags(void)
|
||||
void ClearMysteryGiftFlags(void)
|
||||
{
|
||||
FlagClear(FLAG_MYSTERY_GIFT_DONE);
|
||||
FlagClear(FLAG_MYSTERY_GIFT_1);
|
||||
@@ -149,7 +149,7 @@ void ResetMysteryEventFlags(void)
|
||||
FlagClear(FLAG_MYSTERY_GIFT_15);
|
||||
}
|
||||
|
||||
void ResetMysteryEventVars(void)
|
||||
void ClearMysteryGiftVars(void)
|
||||
{
|
||||
VarSet(VAR_EVENT_PICHU_SLOT, 0);
|
||||
VarSet(VAR_MYSTERY_GIFT_1, 0);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "field_specials.h"
|
||||
#include "item_menu.h"
|
||||
#include "link.h"
|
||||
#include "menews_jisan.h"
|
||||
#include "wonder_news.h"
|
||||
#include "metatile_behavior.h"
|
||||
#include "overworld.h"
|
||||
#include "renewable_hidden_items.h"
|
||||
@@ -215,7 +215,7 @@ int ProcessPlayerFieldInput(struct FieldInput *input)
|
||||
if (input->tookStep)
|
||||
{
|
||||
IncrementGameStat(GAME_STAT_STEPS);
|
||||
MENewsJisanStepCounter();
|
||||
WonderNews_IncrementStepCounter();
|
||||
IncrementRenewableHiddenItemStepCounter();
|
||||
RunMassageCooldownStepCounter();
|
||||
IncrementResortGorgeousStepCounter();
|
||||
|
||||
+12
-12
@@ -28,7 +28,7 @@
|
||||
#include "pokedex.h"
|
||||
#include "text_window.h"
|
||||
#include "menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "naming_screen.h"
|
||||
#include "party_menu.h"
|
||||
#include "dynamic_placeholder_text_util.h"
|
||||
@@ -1950,20 +1950,20 @@ void QuestLog_TryRecordDepartedLocation(void)
|
||||
}
|
||||
}
|
||||
|
||||
u16 BattleCardAction(void)
|
||||
u16 GetMysteryGiftCardStat(void)
|
||||
{
|
||||
switch (gSpecialVar_Result)
|
||||
{
|
||||
case 0:
|
||||
return MEvent_GetBattleCardCount(3);
|
||||
case 1:
|
||||
return MEvent_GetBattleCardCount(4);
|
||||
case 2:
|
||||
return MEvent_GetBattleCardCount(0);
|
||||
case 3:
|
||||
return MEvent_GetBattleCardCount(1);
|
||||
case 4:
|
||||
return MEvent_GetBattleCardCount(2);
|
||||
case GET_NUM_STAMPS:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_NUM_STAMPS);
|
||||
case GET_MAX_STAMPS:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_MAX_STAMPS);
|
||||
case GET_CARD_BATTLES_WON:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_BATTLES_WON);
|
||||
case GET_CARD_BATTLES_LOST:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_BATTLES_LOST);
|
||||
case GET_CARD_NUM_TRADES:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_NUM_TRADES);
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("scr_tool.c"), 3873);
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -481,7 +481,7 @@ static void Task_ExecuteMainMenuSelection(u8 taskId)
|
||||
TrySetUpQuestLogScenes_ElseContinueFromSave(taskId);
|
||||
break;
|
||||
case MAIN_MENU_MYSTERYGIFT:
|
||||
SetMainCallback2(c2_mystery_gift);
|
||||
SetMainCallback2(CB2_InitMysteryGift);
|
||||
HelpSystem_Disable();
|
||||
FreeAllWindowBuffers();
|
||||
DestroyTask(taskId);
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "mevent.h"
|
||||
#include "random.h"
|
||||
#include "event_data.h"
|
||||
#include "menews_jisan.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
static u32 GetMENewsJisanRewardItem(struct WonderNewsMetadata *);
|
||||
static void MENewsJisanIncrementCounterUnk0_5(struct WonderNewsMetadata *);
|
||||
static u32 GetMENewsJisanState(struct WonderNewsMetadata *);
|
||||
static void MENewsJisanIncrementCounterUnk0_2(struct WonderNewsMetadata *);
|
||||
static void MENewsJisanResetCounterUnk0_2(struct WonderNewsMetadata *);
|
||||
|
||||
void MENewsJisan_SetRandomReward(u32 a0)
|
||||
{
|
||||
struct WonderNewsMetadata *r5 = GetMENewsJisanStructPtr();
|
||||
|
||||
r5->unk_0_0 = a0;
|
||||
switch (a0)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
r5->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_RAZZ_BERRY);
|
||||
break;
|
||||
case 3:
|
||||
r5->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_CHERI_BERRY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MENewsJisanReset(void)
|
||||
{
|
||||
struct WonderNewsMetadata *r5 = GetMENewsJisanStructPtr();
|
||||
|
||||
r5->unk_0_0 = 0;
|
||||
r5->unk_0_2 = 0;
|
||||
r5->unk_0_5 = 0;
|
||||
r5->berry = 0;
|
||||
VarSet(VAR_MENEWS_JISAN_STEP_COUNTER, 0);
|
||||
}
|
||||
|
||||
void MENewsJisanStepCounter(void)
|
||||
{
|
||||
u16 *r4 = GetVarPointer(VAR_MENEWS_JISAN_STEP_COUNTER);
|
||||
struct WonderNewsMetadata *r2 = GetMENewsJisanStructPtr();
|
||||
struct WonderNewsMetadata r0 = *r2;
|
||||
|
||||
if ((u8)r0.unk_0_5 > 4 && ++(*r4) >= 500)
|
||||
{
|
||||
r2->unk_0_5 = 0;
|
||||
*r4 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u16 GetMENewsJisanItemAndState(void)
|
||||
{
|
||||
u16 *r6 = &gSpecialVar_Result;
|
||||
struct WonderNewsMetadata *r4 = GetMENewsJisanStructPtr();
|
||||
u16 r5;
|
||||
|
||||
if (!IsMysteryGiftEnabled() || !ValidateReceivedWonderNews())
|
||||
return 0;
|
||||
|
||||
r5 = GetMENewsJisanState(r4);
|
||||
|
||||
switch (r5)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
break;
|
||||
case 2:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
MENewsJisanIncrementCounterUnk0_2(r4);
|
||||
break;
|
||||
case 5:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
MENewsJisanResetCounterUnk0_2(r4);
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
|
||||
return r5;
|
||||
}
|
||||
|
||||
static u32 GetMENewsJisanRewardItem(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
u32 r4;
|
||||
|
||||
a0->unk_0_0 = 0;
|
||||
r4 = a0->berry + FIRST_BERRY_INDEX - 1;
|
||||
a0->berry = 0;
|
||||
MENewsJisanIncrementCounterUnk0_5(a0);
|
||||
return r4;
|
||||
}
|
||||
|
||||
static void MENewsJisanResetCounterUnk0_2(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
a0->unk_0_2 = 0;
|
||||
}
|
||||
|
||||
static void MENewsJisanIncrementCounterUnk0_2(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
a0->unk_0_2++;
|
||||
if ((u8)a0->unk_0_2 > 4)
|
||||
a0->unk_0_2 = 4;
|
||||
}
|
||||
|
||||
static void MENewsJisanIncrementCounterUnk0_5(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
a0->unk_0_5++;
|
||||
if ((u8)a0->unk_0_5 > 5)
|
||||
a0->unk_0_5 = 5;
|
||||
}
|
||||
|
||||
static u32 GetMENewsJisanState(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
struct WonderNewsMetadata r0;
|
||||
if ((u8)a0->unk_0_5 == 5)
|
||||
return 6;
|
||||
|
||||
r0 = *a0;
|
||||
switch (r0.unk_0_0)
|
||||
{
|
||||
case 0:
|
||||
return 3;
|
||||
case 1:
|
||||
return 1;
|
||||
case 2:
|
||||
return 2;
|
||||
case 3:
|
||||
if ((u8)r0.unk_0_2 < 3)
|
||||
return 4;
|
||||
return 5;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("menews_jisan.c"), 383);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-1029
File diff suppressed because it is too large
Load Diff
@@ -1,290 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "decompress.h"
|
||||
#include "overworld.h"
|
||||
#include "script.h"
|
||||
#include "battle_tower.h"
|
||||
#include "mystery_event_script.h"
|
||||
#include "mevent.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
static EWRAM_DATA struct mevent_client * s_mevent_client_ptr = NULL;
|
||||
|
||||
static void mevent_client_init(struct mevent_client *, u32, u32);
|
||||
static u32 mevent_client_exec(struct mevent_client *);
|
||||
static void mevent_client_free_resources(struct mevent_client *);
|
||||
|
||||
extern const struct mevent_client_cmd gMEventClientScript_InitialListen[];
|
||||
|
||||
void mevent_client_do_init(void)
|
||||
{
|
||||
s_mevent_client_ptr = AllocZeroed(sizeof(struct mevent_client));
|
||||
mevent_client_init(s_mevent_client_ptr, 1, 0);
|
||||
}
|
||||
|
||||
u32 mevent_client_do_exec(u16 * a0)
|
||||
{
|
||||
u32 result;
|
||||
if (s_mevent_client_ptr == NULL)
|
||||
return 6;
|
||||
result = mevent_client_exec(s_mevent_client_ptr);
|
||||
if (result == 6)
|
||||
{
|
||||
*a0 = s_mevent_client_ptr->param;
|
||||
mevent_client_free_resources(s_mevent_client_ptr);
|
||||
Free(s_mevent_client_ptr);
|
||||
s_mevent_client_ptr = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void mevent_client_inc_flag(void)
|
||||
{
|
||||
s_mevent_client_ptr->flag++;
|
||||
}
|
||||
|
||||
void *mevent_client_get_buffer(void)
|
||||
{
|
||||
return s_mevent_client_ptr->buffer;
|
||||
}
|
||||
|
||||
void mevent_client_set_param(u32 a0)
|
||||
{
|
||||
s_mevent_client_ptr->param = a0;
|
||||
}
|
||||
|
||||
static void mevent_client_init(struct mevent_client * svr, u32 sendPlayerNo, u32 recvPlayerNo)
|
||||
{
|
||||
svr->unk_00 = 0;
|
||||
svr->mainseqno = 0;
|
||||
svr->flag = 0;
|
||||
svr->sendBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->recvBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->cmdBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->buffer = AllocZeroed(0x40);
|
||||
mevent_srv_sub_init(&svr->manager, sendPlayerNo, recvPlayerNo);
|
||||
}
|
||||
|
||||
static void mevent_client_free_resources(struct mevent_client * svr)
|
||||
{
|
||||
Free(svr->sendBuffer);
|
||||
Free(svr->recvBuffer);
|
||||
Free(svr->cmdBuffer);
|
||||
Free(svr->buffer);
|
||||
}
|
||||
|
||||
static void mevent_client_jmp_buffer(struct mevent_client * svr)
|
||||
{
|
||||
memcpy(svr->cmdBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
|
||||
svr->cmdidx = 0;
|
||||
}
|
||||
|
||||
static void mevent_client_send_word(struct mevent_client * svr, u32 ident, u32 word)
|
||||
{
|
||||
CpuFill32(0, svr->sendBuffer, ME_SEND_BUF_SIZE);
|
||||
*(u32 *)svr->sendBuffer = word;
|
||||
mevent_srv_sub_init_send(&svr->manager, ident, svr->sendBuffer, sizeof(u32));
|
||||
}
|
||||
|
||||
static u32 client_mainseq_0(struct mevent_client * svr)
|
||||
{
|
||||
// init
|
||||
memcpy(svr->cmdBuffer, gMEventClientScript_InitialListen, ME_SEND_BUF_SIZE);
|
||||
svr->cmdidx = 0;
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_1(struct mevent_client * svr)
|
||||
{
|
||||
// done
|
||||
return 6;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_2(struct mevent_client * svr)
|
||||
{
|
||||
// do recv
|
||||
if (mevent_srv_sub_recv(&svr->manager))
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_3(struct mevent_client * svr)
|
||||
{
|
||||
// do send
|
||||
if (mevent_srv_sub_send(&svr->manager))
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_4(struct mevent_client * svr)
|
||||
{
|
||||
// process command
|
||||
struct mevent_client_cmd * cmd = &svr->cmdBuffer[svr->cmdidx];
|
||||
++svr->cmdidx;
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
svr->param = cmd->parameter;
|
||||
svr->mainseqno = 1;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 2:
|
||||
mevent_srv_sub_init_recv(&svr->manager, cmd->parameter, svr->recvBuffer);
|
||||
svr->mainseqno = 2;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 3:
|
||||
svr->mainseqno = 3;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 20:
|
||||
mevent_srv_sub_init_send(&svr->manager, 0x14, svr->sendBuffer, 0);
|
||||
svr->mainseqno = 3;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 19:
|
||||
mevent_client_send_word(svr, 0x12, GetGameStat(cmd->parameter));
|
||||
svr->mainseqno = 3;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 6:
|
||||
if (svr->param == 0)
|
||||
mevent_client_jmp_buffer(svr);
|
||||
break;
|
||||
case 7:
|
||||
if (svr->param == 1)
|
||||
mevent_client_jmp_buffer(svr);
|
||||
break;
|
||||
case 4:
|
||||
mevent_client_jmp_buffer(svr);
|
||||
break;
|
||||
case 5:
|
||||
memcpy(svr->buffer, svr->recvBuffer, 0x40);
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 2;
|
||||
case 11:
|
||||
memcpy(svr->buffer, svr->recvBuffer, 0x40);
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 3;
|
||||
case 12:
|
||||
memcpy(svr->buffer, svr->recvBuffer, 0x40);
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 5;
|
||||
case 13:
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 4;
|
||||
case 8:
|
||||
BuildMEventClientHeader(svr->sendBuffer);
|
||||
mevent_srv_sub_init_send(&svr->manager, 0x11, svr->sendBuffer, sizeof(struct MEventClientHeaderStruct));
|
||||
break;
|
||||
case 14:
|
||||
mevent_client_send_word(svr, 0x13, svr->param);
|
||||
break;
|
||||
case 10:
|
||||
OverwriteSavedWonderCardWithReceivedCard(svr->recvBuffer);
|
||||
break;
|
||||
case 9:
|
||||
if (!MEvent_HaveAlreadyReceivedWonderNews(svr->recvBuffer))
|
||||
{
|
||||
OverwriteSavedWonderNewsWithReceivedNews(svr->recvBuffer);
|
||||
mevent_client_send_word(svr, 0x13, 0);
|
||||
}
|
||||
else
|
||||
// Other trainer already has news
|
||||
mevent_client_send_word(svr, 0x13, 1);
|
||||
break;
|
||||
case 15:
|
||||
svr->mainseqno = 6;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 16:
|
||||
MEvent_ReceiveDistributionMon(svr->recvBuffer);
|
||||
break;
|
||||
case 17:
|
||||
InitRamScript_NoObjectEvent(svr->recvBuffer, 1000);
|
||||
break;
|
||||
case 18:
|
||||
memcpy(&gSaveBlock2Ptr->battleTower.ereaderTrainer, svr->recvBuffer, sizeof(struct BattleTowerEReaderTrainer));
|
||||
ValidateEReaderTrainer();
|
||||
break;
|
||||
case 21:
|
||||
memcpy(gDecompressionBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
|
||||
svr->mainseqno = 7;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_5(struct mevent_client * svr)
|
||||
{
|
||||
// wait flag
|
||||
if (svr->flag)
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_6(struct mevent_client * svr)
|
||||
{
|
||||
// Run mevent buffer script
|
||||
switch (svr->flag)
|
||||
{
|
||||
case 0:
|
||||
MEventScript_InitContext(svr->recvBuffer);
|
||||
++svr->flag;
|
||||
break;
|
||||
case 1:
|
||||
if (!MEventScript_Run(&svr->param))
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_7(struct mevent_client * svr)
|
||||
{
|
||||
// exec arbitrary code
|
||||
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
|
||||
if (func(&svr->param, gSaveBlock2Ptr, gSaveBlock1Ptr) == 1)
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 mevent_client_exec(struct mevent_client * svr)
|
||||
{
|
||||
u32 (*funcs[])(struct mevent_client *) = {
|
||||
client_mainseq_0,
|
||||
client_mainseq_1,
|
||||
client_mainseq_2,
|
||||
client_mainseq_3,
|
||||
client_mainseq_4,
|
||||
client_mainseq_5,
|
||||
client_mainseq_6,
|
||||
client_mainseq_7
|
||||
};
|
||||
return funcs[svr->mainseqno](svr);
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
extern const struct mevent_server_cmd gServerScript_ClientCanceledCard[];
|
||||
|
||||
// Unreferenced
|
||||
const u8 gUnknown_84687A0[] = _("You have collected all STAMPs!\nWant to input a CARD as a prize?");
|
||||
|
||||
/* CLIENT SCRIPTS */
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_InitialListen[] = { // 84687E0
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_Send1442CC[] = {
|
||||
CLI_SNDHEAD,
|
||||
CLI_WAITSND,
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_UnableToRecv[] = { // can't accept card or news
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0a)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_CommError[] = { // comm error
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0b)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_NothingSentOver[] = { // nothing sent
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x00)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_ReceiveCardAndReturnSuccess[] = { // card success
|
||||
CLI_RECEIVE(0x16),
|
||||
CLI_RECVSAV,
|
||||
CLI_RECEIVE(0x19),
|
||||
CLI_RECVRAM,
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x02)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_ReceiveNewsAndValidate[] = {
|
||||
CLI_RECEIVE(0x17),
|
||||
CLI_VLDNEWS,
|
||||
CLI_WAITSND,
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_AlreadyHadNews[] = { // already had news
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x07)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_RecvNewsSuccess[] = { // news success
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x03)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_AskWouldLikeToTossCard[] = {
|
||||
CLI_REQWORD,
|
||||
CLI_SNDWORD,
|
||||
CLI_WAITSND,
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_OtherTrainerCanceled[] = { // comm canceled
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x09)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_AlreadyHadCard[] = { // already had card
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x05)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_SuccessFromBuffer[] = { // success from buffer
|
||||
CLI_RECEIVE(0x15),
|
||||
CLI_RECVBUF,
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0d)
|
||||
};
|
||||
|
||||
/* SERVER SCRIPTS */
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_UnableToSend[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_UnableToRecv),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x0a)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gUnknown_8468950[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_CommError),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x0b)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gUnknown_8468980[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_OtherTrainerCanceled),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x09)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_OtherTrnHasNews[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_AlreadyHadNews),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x07)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SentNewsSuccess[] = {
|
||||
SRV_SEND(0x28, gMEventClientScript_ReceiveNewsAndValidate),
|
||||
SRV_WAITSND,
|
||||
SRV_SEND_NEWS,
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x13),
|
||||
SRV_READWORD,
|
||||
SRV_BRANCHIF(0x01, gMEventSrvScript_OtherTrnHasNews),
|
||||
SRV_SEND(0x10, gMEventClientScript_RecvNewsSuccess),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x03)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SendCardSuccess[] = {
|
||||
SRV_SEND(0x30, gMEventClientScript_ReceiveCardAndReturnSuccess),
|
||||
SRV_WAITSND,
|
||||
SRV_SEND_CARD,
|
||||
SRV_WAITSND,
|
||||
SRV_BUFFER_SEND,
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x02)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_AskClientToOverwriteCard[] = {
|
||||
SRV_SEND(0x28, gMEventClientScript_AskWouldLikeToTossCard),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x13),
|
||||
SRV_READWORD,
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_SendCardSuccess),
|
||||
SRV_BRANCH(gServerScript_ClientCanceledCard)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_OtherTrnHasCard[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_AlreadyHadCard),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x05)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gUnknown_8468B3C[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_NothingSentOver),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x00)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SendNews[] = {
|
||||
SRV_BUFFER_NEWS,
|
||||
SRV_SEND(0x20, gMEventClientScript_Send1442CC),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x11),
|
||||
SRV_READ_1442CC,
|
||||
SRV_VALID_1442CC,
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_UnableToSend),
|
||||
SRV_BRANCH(gMEventSrvScript_SentNewsSuccess)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SendCard[] = {
|
||||
SRV_BUFFER_CARD,
|
||||
SRV_RAM_SCRIPT_IF_VALID,
|
||||
SRV_SEND(0x20, gMEventClientScript_Send1442CC),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x11),
|
||||
SRV_READ_1442CC,
|
||||
SRV_VALID_1442CC,
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_UnableToSend),
|
||||
SRV_CHECK_1442CC_14,
|
||||
SRV_BRANCHIF(0x02, gMEventSrvScript_AskClientToOverwriteCard),
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_SendCardSuccess),
|
||||
SRV_BRANCH(gMEventSrvScript_OtherTrnHasCard)
|
||||
};
|
||||
@@ -1,279 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "script.h"
|
||||
#include "mevent.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
EWRAM_DATA struct mevent_srv_common * s_mevent_srv_common_ptr = NULL;
|
||||
|
||||
static void mevent_srv_init_common(struct mevent_srv_common *, const void *, u32, u32);
|
||||
static void mevent_srv_free_resources(struct mevent_srv_common *);
|
||||
static u32 mevent_srv_exec_common(struct mevent_srv_common *);
|
||||
|
||||
extern const struct mevent_server_cmd gMEventSrvScript_SendNews[];
|
||||
extern const struct mevent_server_cmd gMEventSrvScript_SendCard[];
|
||||
|
||||
void mevent_srv_init_wnews(void)
|
||||
{
|
||||
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
|
||||
mevent_srv_init_common(s_mevent_srv_common_ptr, gMEventSrvScript_SendNews, 0, 1);
|
||||
}
|
||||
|
||||
void mevent_srv_new_wcard(void)
|
||||
{
|
||||
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
|
||||
mevent_srv_init_common(s_mevent_srv_common_ptr, gMEventSrvScript_SendCard, 0, 1);
|
||||
}
|
||||
|
||||
u32 mevent_srv_common_do_exec(u16 * a0)
|
||||
{
|
||||
u32 result;
|
||||
if (s_mevent_srv_common_ptr == NULL)
|
||||
return 3;
|
||||
result = mevent_srv_exec_common(s_mevent_srv_common_ptr);
|
||||
if (result == 3)
|
||||
{
|
||||
*a0 = s_mevent_srv_common_ptr->param;
|
||||
mevent_srv_free_resources(s_mevent_srv_common_ptr);
|
||||
Free(s_mevent_srv_common_ptr);
|
||||
s_mevent_srv_common_ptr = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void mevent_srv_init_common(struct mevent_srv_common * svr, const void *cmdBuffer, u32 sendPlayerNo, u32 recvPlayerNo)
|
||||
{
|
||||
svr->unk_00 = 0;
|
||||
svr->mainseqno = 0;
|
||||
svr->card = AllocZeroed(sizeof(struct WonderCard));
|
||||
svr->news = AllocZeroed(sizeof(struct WonderNews));
|
||||
svr->recvBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->mevent_unk1442cc = AllocZeroed(sizeof(struct MEventClientHeaderStruct));
|
||||
svr->cmdBuffer = cmdBuffer;
|
||||
svr->cmdidx = 0;
|
||||
mevent_srv_sub_init(&svr->manager, sendPlayerNo, recvPlayerNo);
|
||||
}
|
||||
|
||||
static void mevent_srv_free_resources(struct mevent_srv_common * svr)
|
||||
{
|
||||
Free(svr->card);
|
||||
Free(svr->news);
|
||||
Free(svr->recvBuffer);
|
||||
Free(svr->mevent_unk1442cc);
|
||||
}
|
||||
|
||||
static void mevent_srv_common_init_send(struct mevent_srv_common * svr, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
AGB_ASSERT_EX(size <= ME_SEND_BUF_SIZE, ABSPATH("mevent_server.c"), 257);
|
||||
mevent_srv_sub_init_send(&svr->manager, ident, src, size);
|
||||
}
|
||||
|
||||
static void *mevent_first_if_not_null_else_second(void *a0, void *a1)
|
||||
{
|
||||
if (a0 != NULL)
|
||||
return a0;
|
||||
else
|
||||
return a1;
|
||||
}
|
||||
|
||||
static u32 mevent_compare_pointers(void *a0, void *a1)
|
||||
{
|
||||
if (a1 < a0)
|
||||
return 0;
|
||||
else if (a1 == a0)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_0(struct mevent_srv_common * svr)
|
||||
{
|
||||
// start
|
||||
svr->mainseqno = 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_1(struct mevent_srv_common * svr)
|
||||
{
|
||||
// done
|
||||
return 3;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_2(struct mevent_srv_common * svr)
|
||||
{
|
||||
// do recv
|
||||
if (mevent_srv_sub_recv(&svr->manager))
|
||||
svr->mainseqno = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_3(struct mevent_srv_common * svr)
|
||||
{
|
||||
// do send
|
||||
if (mevent_srv_sub_send(&svr->manager))
|
||||
svr->mainseqno = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_4(struct mevent_srv_common * svr)
|
||||
{
|
||||
// process command
|
||||
const struct mevent_server_cmd * cmd = &svr->cmdBuffer[svr->cmdidx];
|
||||
void *ptr;
|
||||
svr->cmdidx++;
|
||||
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case 0:
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 354);
|
||||
svr->mainseqno = 1;
|
||||
svr->param = cmd->flag;
|
||||
break;
|
||||
case 1:
|
||||
svr->mainseqno = 3;
|
||||
break;
|
||||
case 2:
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 364);
|
||||
mevent_srv_sub_init_recv(&svr->manager, cmd->flag, svr->recvBuffer);
|
||||
svr->mainseqno = 2;
|
||||
break;
|
||||
case 3:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 370);
|
||||
svr->cmdidx = 0;
|
||||
svr->cmdBuffer = cmd->parameter;
|
||||
break;
|
||||
case 5:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 376);
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 377);
|
||||
memcpy(svr->mevent_unk1442cc, svr->recvBuffer, sizeof(struct MEventClientHeaderStruct));
|
||||
break;
|
||||
case 6:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 382);
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 383);
|
||||
svr->param = ValidateMEventClientHeader(svr->mevent_unk1442cc);
|
||||
break;
|
||||
case 4:
|
||||
if (svr->param == cmd->flag)
|
||||
{
|
||||
svr->cmdidx = 0;
|
||||
svr->cmdBuffer = cmd->parameter;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 396);
|
||||
ptr = mevent_first_if_not_null_else_second(cmd->parameter, svr->card);
|
||||
svr->param = sub_8144418(ptr, svr->mevent_unk1442cc, ptr);
|
||||
break;
|
||||
case 8:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 402);
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 403);
|
||||
svr->param = *(u32 *)svr->recvBuffer;
|
||||
break;
|
||||
case 9:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 408);
|
||||
ptr = mevent_first_if_not_null_else_second(cmd->parameter, &svr->sendWord);
|
||||
svr->param = MEvent_CanPlayerReceiveDistributionMon(ptr, svr->mevent_unk1442cc, ptr);
|
||||
break;
|
||||
case 10:
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 415);
|
||||
svr->param = sub_81444B0(svr->mevent_unk1442cc, cmd->flag);
|
||||
break;
|
||||
case 11:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 420);
|
||||
svr->param = sub_8144474(svr->mevent_unk1442cc, cmd->parameter);
|
||||
break;
|
||||
case 12:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 426);
|
||||
svr->param = mevent_compare_pointers(cmd->parameter, *(void **)svr->recvBuffer);
|
||||
break;
|
||||
case 14:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 432);
|
||||
mevent_srv_common_init_send(svr, 0x17, mevent_first_if_not_null_else_second(cmd->parameter, svr->news), sizeof(struct WonderNews));
|
||||
break;
|
||||
case 13:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 438);
|
||||
mevent_srv_common_init_send(svr, 0x16, mevent_first_if_not_null_else_second(cmd->parameter, svr->card), sizeof(struct WonderCard));
|
||||
break;
|
||||
case 16:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 444);
|
||||
mevent_srv_common_init_send(svr, 0x18, mevent_first_if_not_null_else_second(cmd->parameter, &svr->sendWord), 4);
|
||||
break;
|
||||
case 15:
|
||||
if (cmd->parameter == NULL)
|
||||
mevent_srv_common_init_send(svr, 0x19, svr->sendBuffer1, svr->sendBuffer1Size);
|
||||
else
|
||||
mevent_srv_common_init_send(svr, 0x19, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 18:
|
||||
if (cmd->parameter == NULL)
|
||||
mevent_srv_common_init_send(svr, 0x10, svr->sendBuffer2, svr->sendBuffer2Size);
|
||||
else
|
||||
mevent_srv_common_init_send(svr, 0x10, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 19:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 466);
|
||||
mevent_srv_common_init_send(svr, 0x1a, cmd->parameter, 188);
|
||||
break;
|
||||
case 20:
|
||||
mevent_srv_common_init_send(svr, 0x15, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 17:
|
||||
mevent_srv_common_init_send(svr, 0x1c, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 22:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 481);
|
||||
memcpy(svr->card, cmd->parameter, 332);
|
||||
break;
|
||||
case 23:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 486);
|
||||
memcpy(svr->news, cmd->parameter, 444);
|
||||
break;
|
||||
case 21:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 491);
|
||||
svr->sendWord = *(u32 *)cmd->parameter;
|
||||
break;
|
||||
case 24:
|
||||
svr->sendBuffer1 = cmd->parameter;
|
||||
svr->sendBuffer1Size = cmd->flag;
|
||||
break;
|
||||
case 25:
|
||||
svr->sendBuffer2 = cmd->parameter;
|
||||
svr->sendBuffer2Size = cmd->flag;
|
||||
break;
|
||||
case 26:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, ABSPATH("mevent_server.c"), 506);
|
||||
memcpy(svr->card, GetSavedWonderCard(), 332);
|
||||
MEvent_WonderCardResetUnk08_6(svr->card);
|
||||
break;
|
||||
case 27:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, ABSPATH("mevent_server.c"), 512);
|
||||
memcpy(svr->news, GetSavedWonderNews(), 444);
|
||||
break;
|
||||
case 28:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, ABSPATH("mevent_server.c"), 517);
|
||||
svr->sendBuffer1 = GetSavedRamScriptIfValid();
|
||||
break;
|
||||
case 29:
|
||||
mevent_srv_common_init_send(svr, 0x1b, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 (*const func_tbl[])(struct mevent_srv_common *) = {
|
||||
common_mainseq_0,
|
||||
common_mainseq_1,
|
||||
common_mainseq_2,
|
||||
common_mainseq_3,
|
||||
common_mainseq_4
|
||||
};
|
||||
|
||||
static u32 mevent_srv_exec_common(struct mevent_srv_common * svr)
|
||||
{
|
||||
u32 response;
|
||||
AGB_ASSERT_EX(svr->mainseqno < NELEMS(func_tbl), ABSPATH("mevent_server.c"), 546);
|
||||
response = func_tbl[svr->mainseqno](svr);
|
||||
AGB_ASSERT_EX(svr->mainseqno < NELEMS(func_tbl), ABSPATH("mevent_server.c"), 548);
|
||||
return response;
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
static u32 mevent_receive_func(struct mevent_srv_sub *);
|
||||
static u32 mevent_send_func(struct mevent_srv_sub *);
|
||||
|
||||
u32 mevent_srv_sub_recv(struct mevent_srv_sub * svr)
|
||||
{
|
||||
return svr->recvFunc(svr);
|
||||
}
|
||||
|
||||
u32 mevent_srv_sub_send(struct mevent_srv_sub * svr)
|
||||
{
|
||||
return svr->sendFunc(svr);
|
||||
}
|
||||
|
||||
void mevent_srv_sub_init(struct mevent_srv_sub * svr, u32 sendPlayerNo, u32 recvPlayerNo)
|
||||
{
|
||||
svr->sendPlayerNo = sendPlayerNo;
|
||||
svr->recvPlayerNo = recvPlayerNo;
|
||||
svr->seqno = 0;
|
||||
svr->sendCRC = 0;
|
||||
svr->sendSize = 0;
|
||||
svr->sendCounter = 0;
|
||||
svr->recvCRC = 0;
|
||||
svr->recvSize = 0;
|
||||
svr->recvCounter = 0;
|
||||
svr->sendBfr = NULL;
|
||||
svr->recvBfr = NULL;
|
||||
svr->sendFunc = mevent_send_func;
|
||||
svr->recvFunc = mevent_receive_func;
|
||||
}
|
||||
|
||||
void mevent_srv_sub_init_send(struct mevent_srv_sub * svr, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
svr->seqno = 0;
|
||||
svr->sendIdent = ident;
|
||||
svr->sendCounter = 0;
|
||||
svr->sendCRC = 0;
|
||||
if (size != 0)
|
||||
svr->sendSize = size;
|
||||
else
|
||||
svr->sendSize = ME_SEND_BUF_SIZE;
|
||||
svr->sendBfr = src;
|
||||
}
|
||||
|
||||
void mevent_srv_sub_init_recv(struct mevent_srv_sub * svr, u32 ident, void *dest)
|
||||
{
|
||||
svr->seqno = 0;
|
||||
svr->recvIdent = ident;
|
||||
svr->recvCounter = 0;
|
||||
svr->recvCRC = 0;
|
||||
svr->recvSize = 0;
|
||||
svr->recvBfr = dest;
|
||||
}
|
||||
|
||||
static void mevent_recv_block(u32 recv_idx, void *dest, size_t size)
|
||||
{
|
||||
memcpy(dest, gBlockRecvBuffer[recv_idx], size);
|
||||
}
|
||||
|
||||
static bool32 mevent_has_received(u32 recv_idx)
|
||||
{
|
||||
if ((GetBlockReceivedStatus() >> recv_idx) & 1)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void mevent_reset_recv(u32 recv_idx)
|
||||
{
|
||||
ResetBlockReceivedFlag(recv_idx);
|
||||
}
|
||||
|
||||
static bool32 mevent_receive_func(struct mevent_srv_sub * svr)
|
||||
{
|
||||
struct send_recv_header header;
|
||||
|
||||
switch (svr->seqno)
|
||||
{
|
||||
case 0:
|
||||
if (mevent_has_received(svr->recvPlayerNo))
|
||||
{
|
||||
mevent_recv_block(svr->recvPlayerNo, &header, sizeof(header));
|
||||
svr->recvSize = header.size;
|
||||
svr->recvCRC = header.crc;
|
||||
if (svr->recvSize > ME_SEND_BUF_SIZE)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else if (svr->recvIdent != header.ident)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
svr->recvCounter = 0;
|
||||
mevent_reset_recv(svr->recvPlayerNo);
|
||||
++svr->seqno;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (mevent_has_received(svr->recvPlayerNo))
|
||||
{
|
||||
size_t blocksiz = svr->recvCounter * 252;
|
||||
if (svr->recvSize - blocksiz <= 252)
|
||||
{
|
||||
mevent_recv_block(svr->recvPlayerNo, svr->recvBfr + blocksiz, svr->recvSize - blocksiz);
|
||||
++svr->recvCounter;
|
||||
++svr->seqno;
|
||||
}
|
||||
else
|
||||
{
|
||||
mevent_recv_block(svr->recvPlayerNo, svr->recvBfr + blocksiz, 252);
|
||||
++svr->recvCounter;
|
||||
}
|
||||
mevent_reset_recv(svr->recvPlayerNo);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (CalcCRC16WithTable(svr->recvBfr, svr->recvSize) != svr->recvCRC)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
svr->seqno = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 mevent_send_func(struct mevent_srv_sub * svr)
|
||||
{
|
||||
struct send_recv_header header;
|
||||
|
||||
switch (svr->seqno)
|
||||
{
|
||||
case 0:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
header.ident = svr->sendIdent;
|
||||
header.size = svr->sendSize;
|
||||
header.crc = CalcCRC16WithTable(svr->sendBfr, svr->sendSize);
|
||||
svr->sendCRC = header.crc;
|
||||
svr->sendCounter = 0;
|
||||
SendBlock(0, &header, sizeof(header));
|
||||
++svr->seqno;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (mevent_has_received(svr->sendPlayerNo))
|
||||
{
|
||||
size_t blocksiz;
|
||||
mevent_reset_recv(svr->sendPlayerNo);
|
||||
blocksiz = 252 * svr->sendCounter;
|
||||
if (svr->sendSize - blocksiz <= 252)
|
||||
{
|
||||
SendBlock(0, svr->sendBfr + blocksiz, svr->sendSize - blocksiz);
|
||||
++svr->sendCounter;
|
||||
++svr->seqno;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendBlock(0, svr->sendBfr + blocksiz, 252);
|
||||
++svr->sendCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (CalcCRC16WithTable(svr->sendBfr, svr->sendSize) != svr->sendCRC)
|
||||
LinkRfu_FatalError();
|
||||
else
|
||||
++svr->seqno;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (mevent_has_received(svr->sendPlayerNo))
|
||||
{
|
||||
mevent_reset_recv(svr->sendPlayerNo);
|
||||
svr->seqno = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,634 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "constants/songs.h"
|
||||
#include "easy_chat.h"
|
||||
#include "task.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "util.h"
|
||||
#include "script.h"
|
||||
#include "event_data.h"
|
||||
#include "battle_tower.h"
|
||||
#include "new_game.h"
|
||||
#include "wonder_news.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "help_system.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "strings.h"
|
||||
|
||||
#define CALC_CRC(data) CalcCRC16WithTable((void *)&(data), sizeof(data))
|
||||
|
||||
static bool32 ValidateWonderNews(const struct WonderNews * src);
|
||||
static void ClearSavedWonderNews(void);
|
||||
static void ClearSavedWonderNewsMetadata(void);
|
||||
static bool32 ValidateWonderCard(const struct WonderCard * src);
|
||||
static void ClearSavedWonderCard(void);
|
||||
static void ClearSavedWonderCardMetadata(void);
|
||||
static void IncrementCardStatForNewTrainer(u32 eventId, u32 trainerId, u32 *idsList, s32 count);
|
||||
static void ClearSavedTrainerIds(void);
|
||||
|
||||
static const u16 sReceivedGiftFlags[] = {
|
||||
FLAG_RECEIVED_AURORA_TICKET,
|
||||
FLAG_RECEIVED_MYSTIC_TICKET,
|
||||
FLAG_RECEIVED_OLD_SEA_MAP, // Not used until Emerald
|
||||
FLAG_WONDER_CARD_UNUSED_1,
|
||||
FLAG_WONDER_CARD_UNUSED_2,
|
||||
FLAG_WONDER_CARD_UNUSED_3,
|
||||
FLAG_WONDER_CARD_UNUSED_4,
|
||||
FLAG_WONDER_CARD_UNUSED_5,
|
||||
FLAG_WONDER_CARD_UNUSED_6,
|
||||
FLAG_WONDER_CARD_UNUSED_7,
|
||||
FLAG_WONDER_CARD_UNUSED_8,
|
||||
FLAG_WONDER_CARD_UNUSED_9,
|
||||
FLAG_WONDER_CARD_UNUSED_10,
|
||||
FLAG_WONDER_CARD_UNUSED_11,
|
||||
FLAG_WONDER_CARD_UNUSED_12,
|
||||
FLAG_WONDER_CARD_UNUSED_13,
|
||||
FLAG_WONDER_CARD_UNUSED_14,
|
||||
FLAG_WONDER_CARD_UNUSED_15,
|
||||
FLAG_WONDER_CARD_UNUSED_16,
|
||||
FLAG_WONDER_CARD_UNUSED_17
|
||||
};
|
||||
|
||||
static EWRAM_DATA bool32 sStatsEnabled = FALSE;
|
||||
|
||||
void ClearMysteryGift(void)
|
||||
{
|
||||
CpuFill32(0, &gSaveBlock1Ptr->mysteryGift, sizeof(gSaveBlock1Ptr->mysteryGift));
|
||||
ClearSavedWonderNewsMetadata();
|
||||
InitQuestionnaireWords();
|
||||
}
|
||||
|
||||
struct WonderNews * GetSavedWonderNews(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.news;
|
||||
}
|
||||
|
||||
struct WonderCard * GetSavedWonderCard(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.card;
|
||||
}
|
||||
|
||||
struct WonderCardMetadata * GetSavedWonderCardMetadata(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
}
|
||||
|
||||
struct WonderNewsMetadata * GetSavedWonderNewsMetadata(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.newsMetadata;
|
||||
}
|
||||
|
||||
u16 * GetQuestionnaireWordsPtr(void)
|
||||
{
|
||||
return gSaveBlock1Ptr->mysteryGift.questionnaireWords;
|
||||
}
|
||||
|
||||
// Equivalent to ClearSavedWonderCardAndRelated, but nothing else to clear
|
||||
void ClearSavedWonderNewsAndRelated(void)
|
||||
{
|
||||
ClearSavedWonderNews();
|
||||
}
|
||||
|
||||
bool32 SaveWonderNews(const struct WonderNews * news)
|
||||
{
|
||||
if (!ValidateWonderNews(news))
|
||||
return FALSE;
|
||||
|
||||
ClearSavedWonderNews();
|
||||
gSaveBlock1Ptr->mysteryGift.news = *news;
|
||||
gSaveBlock1Ptr->mysteryGift.newsCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.news);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ValidateSavedWonderNews(void)
|
||||
{
|
||||
if (CALC_CRC(gSaveBlock1Ptr->mysteryGift.news) != gSaveBlock1Ptr->mysteryGift.newsCrc)
|
||||
return FALSE;
|
||||
if (!ValidateWonderNews(&gSaveBlock1Ptr->mysteryGift.news))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool32 ValidateWonderNews(const struct WonderNews * news)
|
||||
{
|
||||
if (news->id == 0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 IsSendingSavedWonderNewsAllowed(void)
|
||||
{
|
||||
const struct WonderNews * news = &gSaveBlock1Ptr->mysteryGift.news;
|
||||
if (news->sendType == SEND_TYPE_DISALLOWED)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderNews(void)
|
||||
{
|
||||
CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->mysteryGift.news));
|
||||
gSaveBlock1Ptr->mysteryGift.newsCrc = 0;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderNewsMetadata(void)
|
||||
{
|
||||
CpuFill32(0, GetSavedWonderNewsMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.newsMetadata));
|
||||
WonderNews_Reset();
|
||||
}
|
||||
|
||||
bool32 IsWonderNewsSameAsSaved(const u8 * news)
|
||||
{
|
||||
const u8 * savedNews = (const u8 *)&gSaveBlock1Ptr->mysteryGift.news;
|
||||
u32 i;
|
||||
if (!ValidateSavedWonderNews())
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < sizeof(gSaveBlock1Ptr->mysteryGift.news); i++)
|
||||
{
|
||||
if (savedNews[i] != news[i])
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ClearSavedWonderCardAndRelated(void)
|
||||
{
|
||||
ClearSavedWonderCard();
|
||||
ClearSavedWonderCardMetadata();
|
||||
ClearSavedTrainerIds();
|
||||
ClearRamScript();
|
||||
ClearMysteryGiftFlags();
|
||||
ClearMysteryGiftVars();
|
||||
ClearEReaderTrainer(&gSaveBlock2Ptr->battleTower.ereaderTrainer);
|
||||
}
|
||||
|
||||
bool32 SaveWonderCard(const struct WonderCard * card)
|
||||
{
|
||||
struct WonderCardMetadata * metadata;
|
||||
if (!ValidateWonderCard(card))
|
||||
return FALSE;
|
||||
|
||||
ClearSavedWonderCardAndRelated();
|
||||
memcpy(&gSaveBlock1Ptr->mysteryGift.card, card, sizeof(struct WonderCard));
|
||||
gSaveBlock1Ptr->mysteryGift.cardCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.card);
|
||||
metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
metadata->iconSpecies = (&gSaveBlock1Ptr->mysteryGift.card)->iconSpecies;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ValidateSavedWonderCard(void)
|
||||
{
|
||||
if (gSaveBlock1Ptr->mysteryGift.cardCrc != CALC_CRC(gSaveBlock1Ptr->mysteryGift.card))
|
||||
return FALSE;
|
||||
if (!ValidateWonderCard(&gSaveBlock1Ptr->mysteryGift.card))
|
||||
return FALSE;
|
||||
if (!ValidateRamScript())
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool32 ValidateWonderCard(const struct WonderCard * card)
|
||||
{
|
||||
if (card->flagId == 0)
|
||||
return FALSE;
|
||||
if (card->type >= CARD_TYPE_COUNT)
|
||||
return FALSE;
|
||||
if (!(card->sendType == SEND_TYPE_DISALLOWED
|
||||
|| card->sendType == SEND_TYPE_ALLOWED
|
||||
|| card->sendType == SEND_TYPE_ALLOWED_ALWAYS))
|
||||
return FALSE;
|
||||
if (card->bgType >= NUM_WONDER_BGS)
|
||||
return FALSE;
|
||||
if (card->maxStamps > MAX_STAMP_CARD_STAMPS)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 IsSendingSavedWonderCardAllowed(void)
|
||||
{
|
||||
const struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->sendType == SEND_TYPE_DISALLOWED)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderCard(void)
|
||||
{
|
||||
CpuFill32(0, &gSaveBlock1Ptr->mysteryGift.card, sizeof(gSaveBlock1Ptr->mysteryGift.card));
|
||||
gSaveBlock1Ptr->mysteryGift.cardCrc = 0;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderCardMetadata(void)
|
||||
{
|
||||
CpuFill32(0, GetSavedWonderCardMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.cardMetadata));
|
||||
gSaveBlock1Ptr->mysteryGift.cardMetadataCrc = 0;
|
||||
}
|
||||
|
||||
u16 GetWonderCardFlagId(void)
|
||||
{
|
||||
if (ValidateSavedWonderCard())
|
||||
return gSaveBlock1Ptr->mysteryGift.card.flagId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DisableWonderCardSending(struct WonderCard * card)
|
||||
{
|
||||
if (card->sendType == SEND_TYPE_ALLOWED)
|
||||
card->sendType = SEND_TYPE_DISALLOWED;
|
||||
}
|
||||
|
||||
static bool32 IsWonderCardFlagIDInValidRange(u16 flagId)
|
||||
{
|
||||
if (flagId >= WONDER_CARD_FLAG_OFFSET && flagId < WONDER_CARD_FLAG_OFFSET + NUM_WONDER_CARD_FLAGS)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsSavedWonderCardGiftNotReceived(void)
|
||||
{
|
||||
u16 value = GetWonderCardFlagId();
|
||||
if (!IsWonderCardFlagIDInValidRange(value))
|
||||
return FALSE;
|
||||
|
||||
// If flag is set, player has received gift from this card
|
||||
if (FlagGet(sReceivedGiftFlags[value - WONDER_CARD_FLAG_OFFSET]) == TRUE)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static s32 GetNumStampsInMetadata(const struct WonderCardMetadata * data, s32 size)
|
||||
{
|
||||
s32 numStamps = 0;
|
||||
s32 i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (data->stampData[STAMP_ID][i] && data->stampData[STAMP_SPECIES][i])
|
||||
numStamps++;
|
||||
}
|
||||
return numStamps;
|
||||
}
|
||||
|
||||
static bool32 IsStampInMetadata(const struct WonderCardMetadata * metadata, const u16 * stamp, s32 maxStamps)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < maxStamps; i++)
|
||||
{
|
||||
if (metadata->stampData[STAMP_ID][i] == stamp[STAMP_ID])
|
||||
return TRUE;
|
||||
if (metadata->stampData[STAMP_SPECIES][i] == stamp[STAMP_SPECIES])
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 ValidateStamp(const u16 * stamp)
|
||||
{
|
||||
if (stamp[STAMP_ID] == 0)
|
||||
return FALSE;
|
||||
if (stamp[STAMP_SPECIES] == SPECIES_NONE)
|
||||
return FALSE;
|
||||
if (stamp[STAMP_SPECIES] >= NUM_SPECIES)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static s32 GetNumStampsInSavedCard(void)
|
||||
{
|
||||
struct WonderCard * card;
|
||||
if (!ValidateSavedWonderCard())
|
||||
return 0;
|
||||
card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type != CARD_TYPE_STAMP)
|
||||
return 0;
|
||||
return GetNumStampsInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, card->maxStamps);
|
||||
}
|
||||
|
||||
bool32 MysteryGift_TrySaveStamp(const u16 * stamp)
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
s32 maxStamps = card->maxStamps;
|
||||
s32 i;
|
||||
if (!ValidateStamp(stamp))
|
||||
return FALSE;
|
||||
if (IsStampInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, stamp, maxStamps))
|
||||
return FALSE;
|
||||
for (i = 0; i < maxStamps; i++)
|
||||
{
|
||||
if (gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] == 0
|
||||
&& gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] == SPECIES_NONE)
|
||||
{
|
||||
gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] = stamp[STAMP_ID];
|
||||
gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] = stamp[STAMP_SPECIES];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define GAME_DATA_VALID_VAR 0x101
|
||||
|
||||
#if defined(FIRERED)
|
||||
#define VERSION_CODE 1
|
||||
#elif defined(LEAFGREEN)
|
||||
#define VERSION_CODE 2
|
||||
#endif
|
||||
|
||||
void MysteryGift_LoadLinkGameData(struct MysteryGiftLinkGameData * data)
|
||||
{
|
||||
s32 i;
|
||||
CpuFill32(0, data, sizeof(*data));
|
||||
// Magic
|
||||
data->unk_00 = GAME_DATA_VALID_VAR;
|
||||
data->unk_04 = 1;
|
||||
data->unk_08 = 1;
|
||||
data->unk_0C = 1;
|
||||
data->unk_10 = VERSION_CODE;
|
||||
|
||||
// Check whether a card already exists
|
||||
if (ValidateSavedWonderCard())
|
||||
{
|
||||
// Populate fields
|
||||
data->flagId = GetSavedWonderCard()->flagId;
|
||||
data->cardMetadata = *GetSavedWonderCardMetadata();
|
||||
data->maxStamps = GetSavedWonderCard()->maxStamps;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->flagId = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
|
||||
data->questionnaireWords[i] = gSaveBlock1Ptr->mysteryGift.questionnaireWords[i];
|
||||
|
||||
CopyTrainerId(data->playerTrainerId, gSaveBlock2Ptr->playerTrainerId);
|
||||
StringCopy(data->playerName, gSaveBlock2Ptr->playerName);
|
||||
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
||||
data->easyChatProfile[i] = gSaveBlock1Ptr->easyChatProfile[i];
|
||||
|
||||
memcpy(data->gameCode, RomHeaderGameCode, GAME_CODE_LENGTH);
|
||||
data->version = RomHeaderSoftwareVersion;
|
||||
}
|
||||
|
||||
bool32 MysteryGift_ValidateLinkGameData(const struct MysteryGiftLinkGameData * data)
|
||||
{
|
||||
if (data->unk_00 != GAME_DATA_VALID_VAR)
|
||||
return FALSE;
|
||||
if (!(data->unk_04 & 1))
|
||||
return FALSE;
|
||||
if (!(data->unk_08 & 1))
|
||||
return FALSE;
|
||||
if (!(data->unk_0C & 1))
|
||||
return FALSE;
|
||||
if (!(data->unk_10 & 0x0F))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 MysteryGift_CompareCardFlags(const u16 * flagId, const struct MysteryGiftLinkGameData * data, const void *unused)
|
||||
{
|
||||
// Has a Wonder Card already?
|
||||
if (data->flagId == 0)
|
||||
return 0;
|
||||
|
||||
// Has this Wonder Card already?
|
||||
if (*flagId == data->flagId)
|
||||
return 1;
|
||||
|
||||
// Player has a different Wonder Card
|
||||
return 2;
|
||||
}
|
||||
|
||||
u32 MysteryGift_CheckStamps(const u16 * stamp, const struct MysteryGiftLinkGameData * data, const void *unused)
|
||||
{
|
||||
s32 stampsMissing = data->maxStamps - GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps);
|
||||
|
||||
// Has full stamp card?
|
||||
if (stampsMissing == 0)
|
||||
return 1;
|
||||
|
||||
// Already has stamp?
|
||||
if (IsStampInMetadata(&data->cardMetadata, stamp, data->maxStamps))
|
||||
return 3;
|
||||
|
||||
// Only 1 empty stamp left?
|
||||
if (stampsMissing == 1)
|
||||
return 4;
|
||||
|
||||
// This is a new stamp
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool32 MysteryGift_DoesQuestionnaireMatch(const struct MysteryGiftLinkGameData * data, const u16 * words)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
|
||||
{
|
||||
if (data->questionnaireWords[i] != words[i])
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static s32 GetNumStampsInLinkData(const struct MysteryGiftLinkGameData * data)
|
||||
{
|
||||
return GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps);
|
||||
}
|
||||
|
||||
u16 MysteryGift_GetCardStatFromLinkData(const struct MysteryGiftLinkGameData * data, u32 stat)
|
||||
{
|
||||
switch (stat)
|
||||
{
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
return data->cardMetadata.battlesWon;
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
return data->cardMetadata.battlesLost;
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
return data->cardMetadata.numTrades;
|
||||
case CARD_STAT_NUM_STAMPS:
|
||||
return GetNumStampsInLinkData(data);
|
||||
case CARD_STAT_MAX_STAMPS:
|
||||
return data->maxStamps;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 825);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void IncrementCardStat(u32 statType)
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
u16 * stat = NULL;
|
||||
switch (statType)
|
||||
{
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.battlesWon;
|
||||
break;
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.battlesLost;
|
||||
break;
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.numTrades;
|
||||
break;
|
||||
case CARD_STAT_NUM_STAMPS:
|
||||
case CARD_STAT_MAX_STAMPS:
|
||||
break;
|
||||
}
|
||||
if (stat == NULL)
|
||||
{
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 868);
|
||||
}
|
||||
else if (++(*stat) > MAX_WONDER_CARD_STAT)
|
||||
{
|
||||
*stat = MAX_WONDER_CARD_STAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u16 MysteryGift_GetCardStat(u32 stat)
|
||||
{
|
||||
switch (stat)
|
||||
{
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
struct WonderCardMetadata * metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
return metadata->battlesWon;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
struct WonderCardMetadata * metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
return metadata->battlesLost;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
struct WonderCardMetadata * metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
return metadata->numTrades;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_NUM_STAMPS:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_STAMP)
|
||||
return GetNumStampsInSavedCard();
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_MAX_STAMPS:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_STAMP)
|
||||
return card->maxStamps;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 913);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MysteryGift_DisableStats(void)
|
||||
{
|
||||
sStatsEnabled = FALSE;
|
||||
}
|
||||
|
||||
bool32 MysteryGift_TryEnableStatsByFlagId(u16 flagId)
|
||||
{
|
||||
sStatsEnabled = FALSE;
|
||||
if (flagId == 0)
|
||||
return FALSE;
|
||||
if (!ValidateSavedWonderCard())
|
||||
return FALSE;
|
||||
if (gSaveBlock1Ptr->mysteryGift.card.flagId != flagId)
|
||||
return FALSE;
|
||||
sStatsEnabled = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void MysteryGift_TryIncrementStat(u32 stat, u32 trainerId)
|
||||
{
|
||||
if (sStatsEnabled)
|
||||
{
|
||||
switch (stat)
|
||||
{
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
IncrementCardStatForNewTrainer(CARD_STAT_NUM_TRADES,
|
||||
trainerId,
|
||||
gSaveBlock1Ptr->mysteryGift.trainerIds[1],
|
||||
ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[1]));
|
||||
break;
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_WON,
|
||||
trainerId,
|
||||
gSaveBlock1Ptr->mysteryGift.trainerIds[0],
|
||||
ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0]));
|
||||
break;
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_LOST,
|
||||
trainerId,
|
||||
gSaveBlock1Ptr->mysteryGift.trainerIds[0],
|
||||
ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0]));
|
||||
break;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 988);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearSavedTrainerIds(void)
|
||||
{
|
||||
CpuFill32(0, gSaveBlock1Ptr->mysteryGift.trainerIds, sizeof(gSaveBlock1Ptr->mysteryGift.trainerIds));
|
||||
}
|
||||
|
||||
// Returns TRUE if it's a new trainer id, FALSE if an existing one.
|
||||
// In either case the given trainerId is saved in element 0
|
||||
static bool32 RecordTrainerId(u32 trainerId, u32 * trainerIds, s32 size)
|
||||
{
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (trainerIds[i] == trainerId)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == size)
|
||||
{
|
||||
// New trainer, shift array and insert new id at front
|
||||
for (j = size - 1; j > 0; j--)
|
||||
trainerIds[j] = trainerIds[j - 1];
|
||||
|
||||
trainerIds[0] = trainerId;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Existing trainer, shift back to old slot and move id to front
|
||||
for (j = i; j > 0; j--)
|
||||
trainerIds[j] = trainerIds[j - 1];
|
||||
|
||||
trainerIds[0] = trainerId;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void IncrementCardStatForNewTrainer(u32 stat, u32 trainerId, u32 * trainerIds, s32 size)
|
||||
{
|
||||
if (RecordTrainerId(trainerId, trainerIds, size))
|
||||
IncrementCardStat(stat);
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "decompress.h"
|
||||
#include "overworld.h"
|
||||
#include "script.h"
|
||||
#include "battle_tower.h"
|
||||
#include "mystery_event_script.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "mystery_gift_server.h"
|
||||
|
||||
enum {
|
||||
FUNC_INIT,
|
||||
FUNC_DONE,
|
||||
FUNC_RECV,
|
||||
FUNC_SEND,
|
||||
FUNC_RUN,
|
||||
FUNC_WAIT,
|
||||
FUNC_RUN_MEVENT,
|
||||
FUNC_RUN_BUFFER,
|
||||
};
|
||||
|
||||
static EWRAM_DATA struct MysteryGiftClient * sClient = NULL;
|
||||
|
||||
static void MysteryGiftClient_Init(struct MysteryGiftClient *, u32, u32);
|
||||
static u32 MysteryGiftClient_CallFunc(struct MysteryGiftClient *);
|
||||
static void MysteryGiftClient_Free(struct MysteryGiftClient *);
|
||||
|
||||
extern const struct MysteryGiftClientCmd gMysteryGiftClientScript_Init[];
|
||||
|
||||
void MysteryGiftClient_Create(void)
|
||||
{
|
||||
sClient = AllocZeroed(sizeof(*sClient));
|
||||
MysteryGiftClient_Init(sClient, 1, 0);
|
||||
}
|
||||
|
||||
u32 MysteryGiftClient_Run(u16 * endVal)
|
||||
{
|
||||
u32 result;
|
||||
if (sClient == NULL)
|
||||
return CLI_RET_END;
|
||||
result = MysteryGiftClient_CallFunc(sClient);
|
||||
if (result == CLI_RET_END)
|
||||
{
|
||||
*endVal = sClient->param;
|
||||
MysteryGiftClient_Free(sClient);
|
||||
FREE_AND_SET_NULL(sClient);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MysteryGiftClient_AdvanceState(void)
|
||||
{
|
||||
sClient->funcState++;
|
||||
}
|
||||
|
||||
void *MysteryGiftClient_GetMsg(void)
|
||||
{
|
||||
return sClient->msg;
|
||||
}
|
||||
|
||||
void MysteryGiftClient_SetParam(u32 val)
|
||||
{
|
||||
sClient->param = val;
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_Init(struct MysteryGiftClient * client, u32 sendPlayerId, u32 recvPlayerId)
|
||||
{
|
||||
client->unused = 0;
|
||||
client->funcId = FUNC_INIT;
|
||||
client->funcState = 0;
|
||||
client->sendBuffer = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
client->recvBuffer = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
client->script = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
client->msg = AllocZeroed(CLIENT_MAX_MSG_SIZE);
|
||||
MysteryGiftLink_Init(&client->link, sendPlayerId, recvPlayerId);
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_Free(struct MysteryGiftClient * client)
|
||||
{
|
||||
Free(client->sendBuffer);
|
||||
Free(client->recvBuffer);
|
||||
Free(client->script);
|
||||
Free(client->msg);
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_CopyRecvScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
memcpy(client->script, client->recvBuffer, MG_LINK_BUFFER_SIZE);
|
||||
client->cmdidx = 0;
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_InitSendWord(struct MysteryGiftClient * client, u32 ident, u32 word)
|
||||
{
|
||||
CpuFill32(0, client->sendBuffer, MG_LINK_BUFFER_SIZE);
|
||||
*(u32 *)client->sendBuffer = word;
|
||||
MysteryGiftLink_InitSend(&client->link, ident, client->sendBuffer, sizeof(word));
|
||||
}
|
||||
|
||||
static u32 Client_Init(struct MysteryGiftClient * client)
|
||||
{
|
||||
memcpy(client->script, gMysteryGiftClientScript_Init, MG_LINK_BUFFER_SIZE);
|
||||
client->cmdidx = 0;
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_INIT;
|
||||
}
|
||||
|
||||
static u32 Client_Done(struct MysteryGiftClient * client)
|
||||
{
|
||||
return CLI_RET_END;
|
||||
}
|
||||
|
||||
static u32 Client_Recv(struct MysteryGiftClient * client)
|
||||
{
|
||||
if (MysteryGiftLink_Recv(&client->link))
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_Send(struct MysteryGiftClient * client)
|
||||
{
|
||||
if (MysteryGiftLink_Send(&client->link))
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_Run(struct MysteryGiftClient * client)
|
||||
{
|
||||
// process command
|
||||
struct MysteryGiftClientCmd * cmd = &client->script[client->cmdidx];
|
||||
client->cmdidx++;
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case CLI_NONE:
|
||||
break;
|
||||
case CLI_RETURN:
|
||||
client->param = cmd->parameter; // Set for endVal in MysteryGiftClient_Run
|
||||
client->funcId = FUNC_DONE;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_RECV:
|
||||
MysteryGiftLink_InitRecv(&client->link, cmd->parameter, client->recvBuffer);
|
||||
client->funcId = FUNC_RECV;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SEND_LOADED:
|
||||
// Send without a MysteryGiftLink_InitSend
|
||||
// Sends whatever has been loaded already
|
||||
client->funcId = FUNC_SEND;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SEND_READY_END:
|
||||
MysteryGiftLink_InitSend(&client->link, MG_LINKID_READY_END, client->sendBuffer, 0);
|
||||
client->funcId = FUNC_SEND;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SEND_STAT:
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_GAME_STAT, GetGameStat(cmd->parameter));
|
||||
client->funcId = FUNC_SEND;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_COPY_RECV_IF_N:
|
||||
if (client->param == FALSE)
|
||||
MysteryGiftClient_CopyRecvScript(client);
|
||||
break;
|
||||
case CLI_COPY_RECV_IF:
|
||||
if (client->param == TRUE)
|
||||
MysteryGiftClient_CopyRecvScript(client);
|
||||
break;
|
||||
case CLI_COPY_RECV:
|
||||
MysteryGiftClient_CopyRecvScript(client);
|
||||
break;
|
||||
case CLI_YES_NO:
|
||||
memcpy(client->msg, client->recvBuffer, CLIENT_MAX_MSG_SIZE);
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_YES_NO;
|
||||
case CLI_PRINT_MSG:
|
||||
memcpy(client->msg, client->recvBuffer, CLIENT_MAX_MSG_SIZE);
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_PRINT_MSG;
|
||||
case CLI_COPY_MSG:
|
||||
memcpy(client->msg, client->recvBuffer, CLIENT_MAX_MSG_SIZE);
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_COPY_MSG;
|
||||
case CLI_ASK_TOSS:
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_ASK_TOSS;
|
||||
case CLI_LOAD_GAME_DATA:
|
||||
MysteryGift_LoadLinkGameData(client->sendBuffer);
|
||||
MysteryGiftLink_InitSend(&client->link, MG_LINKID_GAME_DATA, client->sendBuffer, sizeof(struct MysteryGiftLinkGameData));
|
||||
break;
|
||||
case CLI_LOAD_TOSS_RESPONSE:
|
||||
// param here is set by MG_STATE_CLIENT_ASK_TOSS or MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_RESPONSE, client->param);
|
||||
break;
|
||||
case CLI_SAVE_CARD:
|
||||
SaveWonderCard(client->recvBuffer);
|
||||
break;
|
||||
case CLI_SAVE_NEWS:
|
||||
if (!IsWonderNewsSameAsSaved(client->recvBuffer))
|
||||
{
|
||||
SaveWonderNews(client->recvBuffer);
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_RESPONSE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wonder News has already been saved (or is invalid).
|
||||
// Prepare a signal to indicate it was not saved.
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_RESPONSE, TRUE);
|
||||
}
|
||||
break;
|
||||
case CLI_RUN_MEVENT_SCRIPT:
|
||||
client->funcId = FUNC_RUN_MEVENT;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SAVE_STAMP:
|
||||
MysteryGift_TrySaveStamp(client->recvBuffer);
|
||||
break;
|
||||
case CLI_SAVE_RAM_SCRIPT:
|
||||
InitRamScript_NoObjectEvent(client->recvBuffer, sizeof(struct RamScriptData));
|
||||
break;
|
||||
case CLI_RECV_EREADER_TRAINER:
|
||||
memcpy(&gSaveBlock2Ptr->battleTower.ereaderTrainer, client->recvBuffer, sizeof(gSaveBlock2Ptr->battleTower.ereaderTrainer));
|
||||
ValidateEReaderTrainer();
|
||||
break;
|
||||
case CLI_RUN_BUFFER_SCRIPT:
|
||||
memcpy(gDecompressionBuffer, client->recvBuffer, MG_LINK_BUFFER_SIZE);
|
||||
client->funcId = FUNC_RUN_BUFFER;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_Wait(struct MysteryGiftClient * client)
|
||||
{
|
||||
if (client->funcState)
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_RunMysteryEventScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
switch (client->funcState)
|
||||
{
|
||||
case 0:
|
||||
MEventScript_InitContext(client->recvBuffer);
|
||||
client->funcState++;
|
||||
break;
|
||||
case 1:
|
||||
if (!MEventScript_Run(&client->param))
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_RunBufferScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
|
||||
if (func(&client->param, gSaveBlock2Ptr, gSaveBlock1Ptr) == 1)
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 MysteryGiftClient_CallFunc(struct MysteryGiftClient * client)
|
||||
{
|
||||
u32 (*funcs[])(struct MysteryGiftClient *) = {
|
||||
[FUNC_INIT] = Client_Init,
|
||||
[FUNC_DONE] = Client_Done,
|
||||
[FUNC_RECV] = Client_Recv,
|
||||
[FUNC_SEND] = Client_Send,
|
||||
[FUNC_RUN] = Client_Run,
|
||||
[FUNC_WAIT] = Client_Wait,
|
||||
[FUNC_RUN_MEVENT] = Client_RunMysteryEventScript,
|
||||
[FUNC_RUN_BUFFER] = Client_RunBufferScript
|
||||
};
|
||||
return funcs[client->funcId](client);
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mystery_gift_server.h"
|
||||
|
||||
/*
|
||||
Handles the link connection functions used by the Mystery Gift client/server.
|
||||
Note: MysteryGiftLink is shortened to MGL for internal functions.
|
||||
*/
|
||||
|
||||
struct SendRecvHeader
|
||||
{
|
||||
u16 ident;
|
||||
u16 crc;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
static u32 MGL_Receive(struct MysteryGiftLink *);
|
||||
static u32 MGL_Send(struct MysteryGiftLink *);
|
||||
|
||||
u32 MysteryGiftLink_Recv(struct MysteryGiftLink * link)
|
||||
{
|
||||
return link->recvFunc(link);
|
||||
}
|
||||
|
||||
u32 MysteryGiftLink_Send(struct MysteryGiftLink * link)
|
||||
{
|
||||
return link->sendFunc(link);
|
||||
}
|
||||
|
||||
void MysteryGiftLink_Init(struct MysteryGiftLink * link, u32 sendPlayerId, u32 recvPlayerId)
|
||||
{
|
||||
link->sendPlayerId = sendPlayerId;
|
||||
link->recvPlayerId = recvPlayerId;
|
||||
link->state = 0;
|
||||
link->sendCRC = 0;
|
||||
link->sendSize = 0;
|
||||
link->sendCounter = 0;
|
||||
link->recvCRC = 0;
|
||||
link->recvSize = 0;
|
||||
link->recvCounter = 0;
|
||||
link->sendBuffer = NULL;
|
||||
link->recvBuffer = NULL;
|
||||
link->sendFunc = MGL_Send;
|
||||
link->recvFunc = MGL_Receive;
|
||||
}
|
||||
|
||||
void MysteryGiftLink_InitSend(struct MysteryGiftLink * link, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
link->state = 0;
|
||||
link->sendIdent = ident;
|
||||
link->sendCounter = 0;
|
||||
link->sendCRC = 0;
|
||||
if (size != 0)
|
||||
link->sendSize = size;
|
||||
else
|
||||
link->sendSize = MG_LINK_BUFFER_SIZE;
|
||||
link->sendBuffer = src;
|
||||
}
|
||||
|
||||
void MysteryGiftLink_InitRecv(struct MysteryGiftLink * link, u32 ident, void *dest)
|
||||
{
|
||||
link->state = 0;
|
||||
link->recvIdent = ident;
|
||||
link->recvCounter = 0;
|
||||
link->recvCRC = 0;
|
||||
link->recvSize = 0;
|
||||
link->recvBuffer = dest;
|
||||
}
|
||||
|
||||
static void MGL_ReceiveBlock(u32 playerId, void *dest, size_t size)
|
||||
{
|
||||
memcpy(dest, gBlockRecvBuffer[playerId], size);
|
||||
}
|
||||
|
||||
static bool32 MGL_HasReceived(u32 playerId)
|
||||
{
|
||||
if ((GetBlockReceivedStatus() >> playerId) & 1)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void MGL_ResetReceived(u32 playerId)
|
||||
{
|
||||
ResetBlockReceivedFlag(playerId);
|
||||
}
|
||||
|
||||
static bool32 MGL_Receive(struct MysteryGiftLink * link)
|
||||
{
|
||||
struct SendRecvHeader header;
|
||||
|
||||
switch (link->state)
|
||||
{
|
||||
case 0:
|
||||
if (MGL_HasReceived(link->recvPlayerId))
|
||||
{
|
||||
MGL_ReceiveBlock(link->recvPlayerId, &header, sizeof(header));
|
||||
link->recvSize = header.size;
|
||||
link->recvCRC = header.crc;
|
||||
if (link->recvSize > MG_LINK_BUFFER_SIZE)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else if (link->recvIdent != header.ident)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
link->recvCounter = 0;
|
||||
MGL_ResetReceived(link->recvPlayerId);
|
||||
link->state++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (MGL_HasReceived(link->recvPlayerId))
|
||||
{
|
||||
size_t blocksize = link->recvCounter * 252;
|
||||
if (link->recvSize - blocksize <= 252)
|
||||
{
|
||||
MGL_ReceiveBlock(link->recvPlayerId, link->recvBuffer + blocksize, link->recvSize - blocksize);
|
||||
link->recvCounter++;
|
||||
link->state++;
|
||||
}
|
||||
else
|
||||
{
|
||||
MGL_ReceiveBlock(link->recvPlayerId, link->recvBuffer + blocksize, 252);
|
||||
link->recvCounter++;
|
||||
}
|
||||
MGL_ResetReceived(link->recvPlayerId);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (CalcCRC16WithTable(link->recvBuffer, link->recvSize) != link->recvCRC)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
link->state = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 MGL_Send(struct MysteryGiftLink * link)
|
||||
{
|
||||
struct SendRecvHeader header;
|
||||
|
||||
switch (link->state)
|
||||
{
|
||||
case 0:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
header.ident = link->sendIdent;
|
||||
header.size = link->sendSize;
|
||||
header.crc = CalcCRC16WithTable(link->sendBuffer, link->sendSize);
|
||||
link->sendCRC = header.crc;
|
||||
link->sendCounter = 0;
|
||||
SendBlock(0, &header, sizeof(header));
|
||||
link->state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (MGL_HasReceived(link->sendPlayerId))
|
||||
{
|
||||
size_t blocksize;
|
||||
MGL_ResetReceived(link->sendPlayerId);
|
||||
blocksize = 252 * link->sendCounter;
|
||||
if (link->sendSize - blocksize <= 252)
|
||||
{
|
||||
SendBlock(0, link->sendBuffer + blocksize, link->sendSize - blocksize);
|
||||
link->sendCounter++;
|
||||
link->state++;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendBlock(0, link->sendBuffer + blocksize, 252);
|
||||
link->sendCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (CalcCRC16WithTable(link->sendBuffer, link->sendSize) != link->sendCRC)
|
||||
LinkRfu_FatalError();
|
||||
else
|
||||
link->state++;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (MGL_HasReceived(link->sendPlayerId))
|
||||
{
|
||||
MGL_ResetReceived(link->sendPlayerId);
|
||||
link->state = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
+548
-600
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
#include "global.h"
|
||||
#include "mystery_gift_server.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "constants/mystery_gift.h"
|
||||
|
||||
extern const struct MysteryGiftServerCmd gServerScript_ClientCanceledCard[];
|
||||
|
||||
// Unreferenced
|
||||
static const u8 sText_CollectedAllStamps[] = _("You have collected all STAMPs!\nWant to input a CARD as a prize?");
|
||||
|
||||
//==================
|
||||
// Client scripts
|
||||
//==================
|
||||
|
||||
const struct MysteryGiftClientCmd gMysteryGiftClientScript_Init[] = {
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_SendGameData[] = {
|
||||
{CLI_LOAD_GAME_DATA},
|
||||
{CLI_SEND_LOADED},
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_CantAccept[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_CANT_ACCEPT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_CommError[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_COMM_ERROR}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_NothingSent[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_NOTHING_SENT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_SaveCard[] = {
|
||||
{CLI_RECV, MG_LINKID_CARD},
|
||||
{CLI_SAVE_CARD},
|
||||
{CLI_RECV, MG_LINKID_RAM_SCRIPT},
|
||||
{CLI_SAVE_RAM_SCRIPT},
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_CARD_RECEIVED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_SaveNews[] = {
|
||||
{CLI_RECV, MG_LINKID_NEWS},
|
||||
{CLI_SAVE_NEWS},
|
||||
{CLI_SEND_LOADED}, // Send whether or not the News was saved (read by sServerScript_SendNews)
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_HadNews[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_HAD_NEWS}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_NewsReceived[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_NEWS_RECEIVED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_AskToss[] = {
|
||||
{CLI_ASK_TOSS},
|
||||
{CLI_LOAD_TOSS_RESPONSE},
|
||||
{CLI_SEND_LOADED},
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_Canceled[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_COMM_CANCELED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_HadCard[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_HAD_CARD}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_DynamicSuccess[] = {
|
||||
{CLI_RECV, MG_LINKID_DYNAMIC_MSG},
|
||||
{CLI_COPY_MSG},
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_BUFFER_SUCCESS}
|
||||
};
|
||||
|
||||
//==================
|
||||
// Server scripts
|
||||
//==================
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_CantSend[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_CantAccept)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CANT_SEND_GIFT_1}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_CommError[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_CommError)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_COMM_ERROR}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_ClientCanceledNews[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_Canceled)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CLIENT_CANCELED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_HasNews[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_HadNews)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_HAS_NEWS}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_SendNews[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SaveNews)},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_NEWS},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_RESPONSE},
|
||||
{SVR_READ_RESPONSE},
|
||||
{SVR_GOTO_IF_EQ, TRUE, sServerScript_HasNews}, // Wonder News was not saved
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_NewsReceived)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_NEWS_SENT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_SendCard[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SaveCard)},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_CARD},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_RAM_SCRIPT},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CARD_SENT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_TossPrompt[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_AskToss)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_RESPONSE},
|
||||
{SVR_READ_RESPONSE},
|
||||
{SVR_GOTO_IF_EQ, FALSE, sServerScript_SendCard}, // Tossed old card, send new one
|
||||
{SVR_GOTO, .ptr = gServerScript_ClientCanceledCard} // Kept old card, cancel new one
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_HasCard[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_HadCard)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_HAS_CARD}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_NothingSent[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_NothingSent)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_NOTHING_SENT}
|
||||
};
|
||||
|
||||
const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderNews[] = {
|
||||
{SVR_COPY_SAVED_NEWS},
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SendGameData)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_GAME_DATA},
|
||||
{SVR_COPY_GAME_DATA},
|
||||
{SVR_CHECK_GAME_DATA},
|
||||
{SVR_GOTO_IF_EQ, FALSE, sServerScript_CantSend},
|
||||
{SVR_GOTO, .ptr = sServerScript_SendNews},
|
||||
};
|
||||
|
||||
const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderCard[] = {
|
||||
{SVR_COPY_SAVED_CARD},
|
||||
{SVR_COPY_SAVED_RAM_SCRIPT},
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SendGameData)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_GAME_DATA},
|
||||
{SVR_COPY_GAME_DATA},
|
||||
{SVR_CHECK_GAME_DATA},
|
||||
{SVR_GOTO_IF_EQ, FALSE, sServerScript_CantSend},
|
||||
{SVR_CHECK_EXISTING_CARD},
|
||||
{SVR_GOTO_IF_EQ, HAS_DIFF_CARD, sServerScript_TossPrompt},
|
||||
{SVR_GOTO_IF_EQ, HAS_NO_CARD, sServerScript_SendCard},
|
||||
{SVR_GOTO, .ptr = sServerScript_HasCard} // HAS_SAME_CARD
|
||||
};
|
||||
@@ -0,0 +1,302 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "script.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_server.h"
|
||||
|
||||
// Assert statements use the original GF names, which are defined below.
|
||||
// Note that their name "flag" is especially misleading,
|
||||
// as it's not a boolean (for example it can contain a size argument).
|
||||
// 'parameter' is shortened to param explicitly to avoid a collision with
|
||||
// the original name for a different field.
|
||||
#define mainseqno funcId
|
||||
#define func_tbl sFuncTable
|
||||
#define parameter ptr
|
||||
#define flag param
|
||||
#define ME_SEND_BUF_SIZE MG_LINK_BUFFER_SIZE
|
||||
#define FILE ABSPATH("mevent_server.c")
|
||||
|
||||
#define ASSERT_PTR_EMPTY(lineNum) AGB_ASSERT_EX(cmd->parameter == NULL, FILE, (lineNum));
|
||||
#define ASSERT_PARAM_EMPTY(lineNum) AGB_ASSERT_EX(cmd->flag == FALSE, FILE, (lineNum));
|
||||
#define ASSERT_PTR_PARAM_EMPTY(lineNum) AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, FILE, (lineNum));
|
||||
#define ASSERT_VALID_FUNC(lineNum) AGB_ASSERT_EX(svr->mainseqno < NELEMS(func_tbl), FILE, (lineNum));
|
||||
#define ASSERT_SIZE_OK(lineNum) AGB_ASSERT_EX(size <= ME_SEND_BUF_SIZE, FILE, (lineNum));
|
||||
|
||||
enum {
|
||||
FUNC_INIT,
|
||||
FUNC_DONE,
|
||||
FUNC_RECV,
|
||||
FUNC_SEND,
|
||||
FUNC_RUN,
|
||||
};
|
||||
|
||||
static EWRAM_DATA struct MysteryGiftServer * sServer = NULL;
|
||||
|
||||
static void MysteryGiftServer_Init(struct MysteryGiftServer *, const void *, u32, u32);
|
||||
static void MysteryGiftServer_Free(struct MysteryGiftServer *);
|
||||
static u32 MysteryGiftServer_CallFunc(struct MysteryGiftServer *);
|
||||
|
||||
extern const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderNews[];
|
||||
extern const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderCard[];
|
||||
|
||||
void MysterGiftServer_CreateForNews(void)
|
||||
{
|
||||
sServer = AllocZeroed(sizeof(*sServer));
|
||||
MysteryGiftServer_Init(sServer, gMysteryGiftServerScript_SendWonderNews, 0, 1);
|
||||
}
|
||||
|
||||
void MysterGiftServer_CreateForCard(void)
|
||||
{
|
||||
sServer = AllocZeroed(sizeof(*sServer));
|
||||
MysteryGiftServer_Init(sServer, gMysteryGiftServerScript_SendWonderCard, 0, 1);
|
||||
}
|
||||
|
||||
u32 MysterGiftServer_Run(u16 * endVal)
|
||||
{
|
||||
u32 result;
|
||||
if (sServer == NULL)
|
||||
return SVR_RET_END;
|
||||
result = MysteryGiftServer_CallFunc(sServer);
|
||||
if (result == SVR_RET_END)
|
||||
{
|
||||
*endVal = sServer->param;
|
||||
MysteryGiftServer_Free(sServer);
|
||||
FREE_AND_SET_NULL(sServer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void MysteryGiftServer_Init(struct MysteryGiftServer * svr, const void *script, u32 sendPlayerId, u32 recvPlayerId)
|
||||
{
|
||||
svr->unused = 0;
|
||||
svr->funcId = FUNC_INIT;
|
||||
svr->card = AllocZeroed(sizeof(*svr->card));
|
||||
svr->news = AllocZeroed(sizeof(*svr->news));
|
||||
svr->recvBuffer = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
svr->linkGameData = AllocZeroed(sizeof(*svr->linkGameData));
|
||||
svr->script = script;
|
||||
svr->cmdidx = 0;
|
||||
MysteryGiftLink_Init(&svr->manager, sendPlayerId, recvPlayerId);
|
||||
}
|
||||
|
||||
static void MysteryGiftServer_Free(struct MysteryGiftServer * svr)
|
||||
{
|
||||
Free(svr->card);
|
||||
Free(svr->news);
|
||||
Free(svr->recvBuffer);
|
||||
Free(svr->linkGameData);
|
||||
}
|
||||
|
||||
static void MysteryGiftServer_InitSend(struct MysteryGiftServer * svr, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
ASSERT_SIZE_OK(257);
|
||||
MysteryGiftLink_InitSend(&svr->manager, ident, src, size);
|
||||
}
|
||||
|
||||
// Given the command pointer parameter and the 'default' normal data.
|
||||
// If the command's pointer is not empty use that as the send data, otherwise use the default.
|
||||
static const void *MysteryGiftServer_GetSendData(const void *dynamicData, const void *defaultData)
|
||||
{
|
||||
if (dynamicData != NULL)
|
||||
return dynamicData;
|
||||
else
|
||||
return defaultData;
|
||||
}
|
||||
|
||||
static u32 MysteryGiftServer_Compare(const void *a, const void *b)
|
||||
{
|
||||
if (b < a)
|
||||
return 0;
|
||||
else if (b == a)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
static u32 Server_Init(struct MysteryGiftServer * svr)
|
||||
{
|
||||
svr->funcId = FUNC_RUN;
|
||||
return SVR_RET_INIT;
|
||||
}
|
||||
|
||||
static u32 Server_Done(struct MysteryGiftServer * svr)
|
||||
{
|
||||
return SVR_RET_END;
|
||||
}
|
||||
|
||||
static u32 Server_Recv(struct MysteryGiftServer * svr)
|
||||
{
|
||||
if (MysteryGiftLink_Recv(&svr->manager))
|
||||
svr->funcId = FUNC_RUN;
|
||||
return SVR_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Server_Send(struct MysteryGiftServer * svr)
|
||||
{
|
||||
if (MysteryGiftLink_Send(&svr->manager))
|
||||
svr->funcId = FUNC_RUN;
|
||||
return SVR_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Server_Run(struct MysteryGiftServer * svr)
|
||||
{
|
||||
// process command
|
||||
const struct MysteryGiftServerCmd * cmd = &svr->script[svr->cmdidx];
|
||||
const void *ptr;
|
||||
svr->cmdidx++;
|
||||
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case SVR_RETURN:
|
||||
ASSERT_PTR_EMPTY(354);
|
||||
svr->funcId = FUNC_DONE;
|
||||
svr->param = cmd->param; // Set for endVal in MysteryGiftServer_Run
|
||||
break;
|
||||
case SVR_SEND:
|
||||
svr->funcId = FUNC_SEND;
|
||||
break;
|
||||
case SVR_RECV:
|
||||
ASSERT_PTR_EMPTY(364);
|
||||
MysteryGiftLink_InitRecv(&svr->manager, cmd->param, svr->recvBuffer);
|
||||
svr->funcId = FUNC_RECV;
|
||||
break;
|
||||
case SVR_GOTO:
|
||||
ASSERT_PARAM_EMPTY(370);
|
||||
svr->cmdidx = 0;
|
||||
svr->script = cmd->ptr;
|
||||
break;
|
||||
case SVR_COPY_GAME_DATA:
|
||||
ASSERT_PARAM_EMPTY(376);
|
||||
ASSERT_PTR_EMPTY(377);
|
||||
memcpy(svr->linkGameData, svr->recvBuffer, sizeof(*svr->linkGameData));
|
||||
break;
|
||||
case SVR_CHECK_GAME_DATA:
|
||||
ASSERT_PARAM_EMPTY(382);
|
||||
ASSERT_PTR_EMPTY(383);
|
||||
svr->param = MysteryGift_ValidateLinkGameData(svr->linkGameData);
|
||||
break;
|
||||
case SVR_GOTO_IF_EQ:
|
||||
if (svr->param == cmd->param)
|
||||
{
|
||||
svr->cmdidx = 0;
|
||||
svr->script = cmd->ptr;
|
||||
}
|
||||
break;
|
||||
case SVR_CHECK_EXISTING_CARD:
|
||||
ASSERT_PARAM_EMPTY(396);
|
||||
ptr = MysteryGiftServer_GetSendData(cmd->ptr, svr->card);
|
||||
svr->param = MysteryGift_CompareCardFlags(ptr, svr->linkGameData, ptr);
|
||||
break;
|
||||
case SVR_READ_RESPONSE:
|
||||
ASSERT_PARAM_EMPTY(402);
|
||||
ASSERT_PTR_EMPTY(403);
|
||||
svr->param = *(u32 *)svr->recvBuffer;
|
||||
break;
|
||||
case SVR_CHECK_EXISTING_STAMPS:
|
||||
ASSERT_PARAM_EMPTY(408);
|
||||
ptr = MysteryGiftServer_GetSendData(cmd->ptr, &svr->stamp);
|
||||
svr->param = MysteryGift_CheckStamps(ptr, svr->linkGameData, ptr);
|
||||
break;
|
||||
case SVR_GET_CARD_STAT:
|
||||
ASSERT_PTR_EMPTY(415);
|
||||
svr->param = MysteryGift_GetCardStatFromLinkData(svr->linkGameData, cmd->param);
|
||||
break;
|
||||
case SVR_CHECK_QUESTIONNAIRE:
|
||||
ASSERT_PARAM_EMPTY(420);
|
||||
svr->param = MysteryGift_DoesQuestionnaireMatch(svr->linkGameData, cmd->ptr);
|
||||
break;
|
||||
case SVR_COMPARE:
|
||||
ASSERT_PARAM_EMPTY(426);
|
||||
svr->param = MysteryGiftServer_Compare(cmd->ptr, *(void **)svr->recvBuffer);
|
||||
break;
|
||||
case SVR_LOAD_NEWS:
|
||||
ASSERT_PARAM_EMPTY(432);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_NEWS, MysteryGiftServer_GetSendData(cmd->ptr, svr->news), sizeof(struct WonderNews));
|
||||
break;
|
||||
case SVR_LOAD_CARD:
|
||||
ASSERT_PARAM_EMPTY(438);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_CARD, MysteryGiftServer_GetSendData(cmd->ptr, svr->card), sizeof(struct WonderCard));
|
||||
break;
|
||||
case SVR_LOAD_STAMP:
|
||||
ASSERT_PARAM_EMPTY(444);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_STAMP, MysteryGiftServer_GetSendData(cmd->ptr, &svr->stamp), sizeof(svr->stamp));
|
||||
break;
|
||||
case SVR_LOAD_RAM_SCRIPT:
|
||||
if (cmd->ptr == NULL)
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_RAM_SCRIPT, svr->ramScript, svr->ramScriptSize);
|
||||
else
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_RAM_SCRIPT, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_LOAD_CLIENT_SCRIPT:
|
||||
if (cmd->ptr == NULL)
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_CLIENT_SCRIPT, svr->clientScript, svr->clientScriptSize);
|
||||
else
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_CLIENT_SCRIPT, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_LOAD_EREADER_TRAINER:
|
||||
ASSERT_PARAM_EMPTY(466);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_EREADER_TRAINER, cmd->ptr, sizeof(struct BattleTowerEReaderTrainer));
|
||||
break;
|
||||
case SVR_LOAD_MSG:
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_DYNAMIC_MSG, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_LOAD_UNK_2:
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_UNK_2, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_COPY_CARD:
|
||||
ASSERT_PARAM_EMPTY(481);
|
||||
memcpy(svr->card, cmd->ptr, sizeof(*svr->card));
|
||||
break;
|
||||
case SVR_COPY_NEWS:
|
||||
ASSERT_PARAM_EMPTY(486);
|
||||
memcpy(svr->news, cmd->ptr, sizeof(*svr->news));
|
||||
break;
|
||||
case SVR_COPY_STAMP:
|
||||
ASSERT_PARAM_EMPTY(491);
|
||||
svr->stamp = *(u32 *)cmd->ptr;
|
||||
break;
|
||||
case SVR_SET_RAM_SCRIPT:
|
||||
svr->ramScript = cmd->ptr;
|
||||
svr->ramScriptSize = cmd->param;
|
||||
break;
|
||||
case SVR_SET_CLIENT_SCRIPT:
|
||||
svr->clientScript = cmd->ptr;
|
||||
svr->clientScriptSize = cmd->param;
|
||||
break;
|
||||
case SVR_COPY_SAVED_CARD:
|
||||
ASSERT_PTR_PARAM_EMPTY(506);
|
||||
memcpy(svr->card, GetSavedWonderCard(), sizeof(*svr->card));
|
||||
DisableWonderCardSending(svr->card);
|
||||
break;
|
||||
case SVR_COPY_SAVED_NEWS:
|
||||
ASSERT_PTR_PARAM_EMPTY(512);
|
||||
memcpy(svr->news, GetSavedWonderNews(), sizeof(*svr->news));
|
||||
break;
|
||||
case SVR_COPY_SAVED_RAM_SCRIPT:
|
||||
ASSERT_PTR_PARAM_EMPTY(517);
|
||||
svr->ramScript = GetSavedRamScriptIfValid();
|
||||
break;
|
||||
case SVR_LOAD_UNK_1:
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_UNK_1, cmd->ptr, cmd->param);
|
||||
break;
|
||||
}
|
||||
|
||||
return SVR_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 (*const sFuncTable[])(struct MysteryGiftServer *) = {
|
||||
[FUNC_INIT] = Server_Init,
|
||||
[FUNC_DONE] = Server_Done,
|
||||
[FUNC_RECV] = Server_Recv,
|
||||
[FUNC_SEND] = Server_Send,
|
||||
[FUNC_RUN] = Server_Run
|
||||
};
|
||||
|
||||
static u32 MysteryGiftServer_CallFunc(struct MysteryGiftServer * svr)
|
||||
{
|
||||
u32 response;
|
||||
ASSERT_VALID_FUNC(546)
|
||||
response = sFuncTable[svr->funcId](svr);
|
||||
ASSERT_VALID_FUNC(548)
|
||||
return response;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "new_menu_helpers.h"
|
||||
#include "pokemon_icon.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "battle_anim.h"
|
||||
#include "constants/mystery_gift.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "gflib.h"
|
||||
#include "menu_indicators.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "menu.h"
|
||||
#include "link_rfu.h"
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@
|
||||
#include "berry.h"
|
||||
#include "easy_chat.h"
|
||||
#include "union_room_chat.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "renewable_hidden_items.h"
|
||||
#include "trainer_tower.h"
|
||||
#include "script.h"
|
||||
@@ -143,7 +143,7 @@ void NewGameInitData(void)
|
||||
ResetTrainerFanClub();
|
||||
UnionRoomChat_InitializeRegisteredTexts();
|
||||
ResetMiniGamesResults();
|
||||
InitMEventData();
|
||||
ClearMysteryGift();
|
||||
SetAllRenewableItemFlags();
|
||||
WarpToPlayersRoom();
|
||||
RunScriptImmediately(EventScript_ResetAllMapFlags);
|
||||
|
||||
+170
-131
@@ -4,160 +4,191 @@
|
||||
#include "task.h"
|
||||
#include "wild_pokemon_area.h"
|
||||
#include "pokedex_area_markers.h"
|
||||
#include "pokedex.h"
|
||||
|
||||
/*
|
||||
Controls the red ellipse markers that appear on the pokedex maps to show where a species is found.
|
||||
All of the markers together are a single sprite, with each individual marker being represented by
|
||||
a subsprite of the necessary size and shape.
|
||||
|
||||
The data about each area marker is in sAreaMarkers, each specified by a DEX_AREA constant.
|
||||
A MAPSEC is associated with a DEX_AREA constant by a series of arrays in wild_pokemon_area.c
|
||||
*/
|
||||
|
||||
struct PAM_TaskData
|
||||
{
|
||||
struct SubspriteTable subsprites;
|
||||
void *buffer;
|
||||
u8 unused;
|
||||
u8 spriteId;
|
||||
u16 tilesTag;
|
||||
u16 paletteTag; // Never read
|
||||
};
|
||||
|
||||
enum {
|
||||
MARKER_CIRCULAR,
|
||||
MARKER_SMALL_H,
|
||||
MARKER_SMALL_V,
|
||||
MARKER_MED_H,
|
||||
MARKER_MED_V,
|
||||
MARKER_LARGE_H,
|
||||
MARKER_LARGE_V,
|
||||
};
|
||||
|
||||
static const u16 sMarkerPal[] = INCBIN_U16("graphics/pokedex/area_markers/marker.gbapal");
|
||||
static const u32 sMarkerTiles[] = INCBIN_U32("graphics/pokedex/area_markers/marker.4bpp.lz");
|
||||
|
||||
static const struct Subsprite sSubsprite0 = {
|
||||
.size = ST_OAM_SIZE_0,
|
||||
.shape = ST_OAM_SQUARE,
|
||||
static const struct Subsprite sSubsprite_Circular = {
|
||||
.size = SPRITE_SIZE(8x8),
|
||||
.shape = SPRITE_SHAPE(8x8),
|
||||
.priority = 1,
|
||||
.tileOffset = 0
|
||||
};
|
||||
|
||||
static const struct Subsprite sSubsprite1 = {
|
||||
.size = ST_OAM_SIZE_0,
|
||||
.shape = ST_OAM_H_RECTANGLE,
|
||||
static const struct Subsprite sSubsprite_SmallHorizontal = {
|
||||
.size = SPRITE_SIZE(16x8),
|
||||
.shape = SPRITE_SHAPE(16x8),
|
||||
.priority = 1,
|
||||
.tileOffset = 1
|
||||
};
|
||||
|
||||
static const struct Subsprite sSubsprite2 = {
|
||||
.size = ST_OAM_SIZE_0,
|
||||
.shape = ST_OAM_V_RECTANGLE,
|
||||
static const struct Subsprite sSubsprite_SmallVertical = {
|
||||
.size = SPRITE_SIZE(8x16),
|
||||
.shape = SPRITE_SHAPE(8x16),
|
||||
.priority = 1,
|
||||
.tileOffset = 3
|
||||
};
|
||||
|
||||
static const struct Subsprite sSubsprite3 = {
|
||||
.size = ST_OAM_SIZE_2,
|
||||
.shape = ST_OAM_H_RECTANGLE,
|
||||
static const struct Subsprite sSubsprite_MediumHorizontal = {
|
||||
.size = SPRITE_SIZE(32x16),
|
||||
.shape = SPRITE_SHAPE(32x16),
|
||||
.priority = 1,
|
||||
.tileOffset = 5
|
||||
};
|
||||
|
||||
static const struct Subsprite sSubsprite4 = {
|
||||
.size = ST_OAM_SIZE_2,
|
||||
.shape = ST_OAM_V_RECTANGLE,
|
||||
static const struct Subsprite sSubsprite_MediumVertical = {
|
||||
.size = SPRITE_SIZE(16x32),
|
||||
.shape = SPRITE_SHAPE(16x32),
|
||||
.priority = 1,
|
||||
.tileOffset = 13
|
||||
};
|
||||
|
||||
static const struct Subsprite sSubsprite5 = {
|
||||
.size = ST_OAM_SIZE_2,
|
||||
.shape = ST_OAM_H_RECTANGLE,
|
||||
static const struct Subsprite sSubsprite_LargeHorizontal = {
|
||||
.size = SPRITE_SIZE(32x16),
|
||||
.shape = SPRITE_SHAPE(32x16),
|
||||
.priority = 1,
|
||||
.tileOffset = 21
|
||||
};
|
||||
|
||||
static const struct Subsprite sSubsprite6 = {
|
||||
.size = ST_OAM_SIZE_2,
|
||||
.shape = ST_OAM_V_RECTANGLE,
|
||||
static const struct Subsprite sSubsprite_LargeVertical = {
|
||||
.size = SPRITE_SIZE(16x32),
|
||||
.shape = SPRITE_SHAPE(16x32),
|
||||
.priority = 1,
|
||||
.tileOffset = 29
|
||||
};
|
||||
|
||||
|
||||
static const struct Subsprite *const sSubsprites[] = {
|
||||
&sSubsprite0,
|
||||
&sSubsprite1,
|
||||
&sSubsprite2,
|
||||
&sSubsprite3,
|
||||
&sSubsprite4,
|
||||
&sSubsprite5,
|
||||
&sSubsprite6
|
||||
[MARKER_CIRCULAR] = &sSubsprite_Circular,
|
||||
[MARKER_SMALL_H] = &sSubsprite_SmallHorizontal,
|
||||
[MARKER_SMALL_V] = &sSubsprite_SmallVertical,
|
||||
[MARKER_MED_H] = &sSubsprite_MediumHorizontal,
|
||||
[MARKER_MED_V] = &sSubsprite_MediumVertical,
|
||||
[MARKER_LARGE_H] = &sSubsprite_LargeHorizontal,
|
||||
[MARKER_LARGE_V] = &sSubsprite_LargeVertical
|
||||
};
|
||||
|
||||
static const s8 sSubspriteLookupTable[][4] = {
|
||||
{ 0, 0x00, 0x00 },
|
||||
{ 0, 0x36, 0x2c },
|
||||
{ 0, 0x36, 0x1c },
|
||||
{ 0, 0x36, 0x0c },
|
||||
{ 0, 0x5c, 0x0c },
|
||||
{ 0, 0x6e, 0x18 },
|
||||
{ 0, 0x5c, 0x24 },
|
||||
{ 0, 0x4c, 0x18 },
|
||||
{ 0, 0x4e, 0x34 },
|
||||
{ 0, 0x36, 0x3e },
|
||||
{ 0, 0x2a, 0x02 },
|
||||
{ 0, 0x5c, 0x18 },
|
||||
{ 2, 0x36, 0x20 },
|
||||
{ 2, 0x36, 0x10 },
|
||||
{ 1, 0x3d, 0x0c },
|
||||
{ 1, 0x4d, 0x0c },
|
||||
{ 0, 0x5c, 0x12 },
|
||||
{ 0, 0x5c, 0x1e },
|
||||
{ 0, 0x54, 0x18 },
|
||||
{ 1, 0x62, 0x18 },
|
||||
{ 1, 0x62, 0x0c },
|
||||
{ 2, 0x6e, 0x0c },
|
||||
{ 1, 0x62, 0x24 },
|
||||
{ 4, 0x6a, 0x19 },
|
||||
{ 1, 0x64, 0x2e },
|
||||
{ 2, 0x5e, 0x2d },
|
||||
{ 1, 0x55, 0x34 },
|
||||
{ 0, 0x44, 0x18 },
|
||||
{ 4, 0x3e, 0x1a },
|
||||
{ 1, 0x40, 0x34 },
|
||||
{ 0, 0x4e, 0x3c },
|
||||
{ 3, 0x37, 0x3a },
|
||||
{ 2, 0x36, 0x32 },
|
||||
{ 1, 0x28, 0x1c },
|
||||
{ 4, 0x26, 0x04 },
|
||||
{ 0, 0x5c, 0x04 },
|
||||
{ 3, 0x5a, 0xfe },
|
||||
{ 0, 0x33, 0x14 },
|
||||
{ 1, 0x3d, 0x12 },
|
||||
{ 0, 0x48, 0x08 },
|
||||
{ 0, 0x57, 0x08 },
|
||||
{ 0, 0x70, 0x0e },
|
||||
{ 0, 0x71, 0x14 },
|
||||
{ 0, 0x71, 0x19 },
|
||||
{ 1, 0x4e, 0x2c },
|
||||
{ 0, 0x41, 0x3c },
|
||||
{ 0, 0x34, 0x3e },
|
||||
{ 0, 0x2d, 0x07 },
|
||||
{ 0, 0x0a, 0x0a },
|
||||
{ 0, 0x0c, 0x23 },
|
||||
{ 0, 0x0e, 0x34 },
|
||||
{ 0, 0x0c, 0x54 },
|
||||
{ 0, 0x2d, 0x51 },
|
||||
{ 0, 0x4c, 0x54 },
|
||||
{ 0, 0x68, 0x52 },
|
||||
{ 2, 0x0e, 0x02 },
|
||||
{ 0, 0x0a, 0x0f },
|
||||
{ 0, 0x0c, 0x1d },
|
||||
{ 1, 0x02, 0x34 },
|
||||
{ 1, 0x0c, 0x38 },
|
||||
{ 1, 0x2c, 0x4a },
|
||||
{ 1, 0x24, 0x4e },
|
||||
{ 2, 0x30, 0x50 },
|
||||
{ 2, 0x34, 0x56 },
|
||||
{ 0, 0x48, 0x4a },
|
||||
{ 1, 0x48, 0x4e },
|
||||
{ 2, 0x51, 0x50 },
|
||||
{ 0, 0x4c, 0x5c },
|
||||
{ 0, 0x68, 0x4b },
|
||||
{ 0, 0x68, 0x56 },
|
||||
{ 2, 0x6c, 0x53 },
|
||||
{ 3, 0x60, 0x5a },
|
||||
{ 0, 0x0e, 0x01 },
|
||||
{ 0, 0x05, 0x34 },
|
||||
{ 0, 0x0d, 0x50 },
|
||||
{ 0, 0x36, 0x4a },
|
||||
{ 0, 0x45, 0x49 },
|
||||
{ 0, 0x4c, 0x4d },
|
||||
{ 0, 0x49, 0x5f },
|
||||
{ 3, 0x60, 0x5a }
|
||||
static const s8 sAreaMarkers[][4] = {
|
||||
// Marker, x, y
|
||||
[DEX_AREA_NONE] = {},
|
||||
[DEX_AREA_PALLET_TOWN] = { MARKER_CIRCULAR, 54, 44 },
|
||||
[DEX_AREA_VIRIDIAN_CITY] = { MARKER_CIRCULAR, 54, 28 },
|
||||
[DEX_AREA_PEWTER_CITY] = { MARKER_CIRCULAR, 54, 12 },
|
||||
[DEX_AREA_CERULEAN_CITY] = { MARKER_CIRCULAR, 92, 12 },
|
||||
[DEX_AREA_LAVENDER_TOWN] = { MARKER_CIRCULAR, 110, 24 },
|
||||
[DEX_AREA_VERMILION_CITY] = { MARKER_CIRCULAR, 92, 36 },
|
||||
[DEX_AREA_CELADON_CITY] = { MARKER_CIRCULAR, 76, 24 },
|
||||
[DEX_AREA_FUCHSIA_CITY] = { MARKER_CIRCULAR, 78, 52 },
|
||||
[DEX_AREA_CINNABAR_ISLAND] = { MARKER_CIRCULAR, 54, 62 },
|
||||
[DEX_AREA_INDIGO_PLATEAU] = { MARKER_CIRCULAR, 42, 2 },
|
||||
[DEX_AREA_SAFFRON_CITY] = { MARKER_CIRCULAR, 92, 24 },
|
||||
[DEX_AREA_ROUTE_1] = { MARKER_SMALL_V, 54, 32 },
|
||||
[DEX_AREA_ROUTE_2] = { MARKER_SMALL_V, 54, 16 },
|
||||
[DEX_AREA_ROUTE_3] = { MARKER_SMALL_H, 61, 12 },
|
||||
[DEX_AREA_ROUTE_4] = { MARKER_SMALL_H, 77, 12 },
|
||||
[DEX_AREA_ROUTE_5] = { MARKER_CIRCULAR, 92, 18 },
|
||||
[DEX_AREA_ROUTE_6] = { MARKER_CIRCULAR, 92, 30 },
|
||||
[DEX_AREA_ROUTE_7] = { MARKER_CIRCULAR, 84, 24 },
|
||||
[DEX_AREA_ROUTE_8] = { MARKER_SMALL_H, 98, 24 },
|
||||
[DEX_AREA_ROUTE_9] = { MARKER_SMALL_H, 98, 12 },
|
||||
[DEX_AREA_ROUTE_10] = { MARKER_SMALL_V, 110, 12 },
|
||||
[DEX_AREA_ROUTE_11] = { MARKER_SMALL_H, 98, 36 },
|
||||
[DEX_AREA_ROUTE_12] = { MARKER_MED_V, 106, 25 },
|
||||
[DEX_AREA_ROUTE_13] = { MARKER_SMALL_H, 100, 46 },
|
||||
[DEX_AREA_ROUTE_14] = { MARKER_SMALL_V, 94, 45 },
|
||||
[DEX_AREA_ROUTE_15] = { MARKER_SMALL_H, 85, 52 },
|
||||
[DEX_AREA_ROUTE_16] = { MARKER_CIRCULAR, 68, 24 },
|
||||
[DEX_AREA_ROUTE_17] = { MARKER_MED_V, 62, 26 },
|
||||
[DEX_AREA_ROUTE_18] = { MARKER_SMALL_H, 64, 52 },
|
||||
[DEX_AREA_ROUTE_19] = { MARKER_CIRCULAR, 78, 60 },
|
||||
[DEX_AREA_ROUTE_20] = { MARKER_MED_H, 55, 58 },
|
||||
[DEX_AREA_ROUTE_21] = { MARKER_SMALL_V, 54, 50 },
|
||||
[DEX_AREA_ROUTE_22] = { MARKER_SMALL_H, 40, 28 },
|
||||
[DEX_AREA_ROUTE_23] = { MARKER_MED_V, 38, 4 },
|
||||
[DEX_AREA_ROUTE_24] = { MARKER_CIRCULAR, 92, 4 },
|
||||
[DEX_AREA_ROUTE_25] = { MARKER_MED_H, 90, -2 },
|
||||
[DEX_AREA_VIRIDIAN_FOREST] = { MARKER_CIRCULAR, 51, 20 },
|
||||
[DEX_AREA_DIGLETTS_CAVE] = { MARKER_SMALL_H, 61, 18 },
|
||||
[DEX_AREA_MT_MOON] = { MARKER_CIRCULAR, 72, 8 },
|
||||
[DEX_AREA_CERULEAN_CAVE] = { MARKER_CIRCULAR, 87, 8 },
|
||||
[DEX_AREA_ROCK_TUNNEL] = { MARKER_CIRCULAR, 112, 14 },
|
||||
[DEX_AREA_POWER_PLANT] = { MARKER_CIRCULAR, 113, 20 },
|
||||
[DEX_AREA_POKEMON_TOWER] = { MARKER_CIRCULAR, 113, 25 },
|
||||
[DEX_AREA_SAFARI_ZONE] = { MARKER_SMALL_H, 78, 44 },
|
||||
[DEX_AREA_SEAFOAM_ISLANDS] = { MARKER_CIRCULAR, 65, 60 },
|
||||
[DEX_AREA_POKEMON_MANSION] = { MARKER_CIRCULAR, 52, 62 },
|
||||
[DEX_AREA_VICTORY_ROAD] = { MARKER_CIRCULAR, 45, 7 },
|
||||
[DEX_AREA_ONE_ISLAND] = { MARKER_CIRCULAR, 10, 10 },
|
||||
[DEX_AREA_TWO_ISLAND] = { MARKER_CIRCULAR, 12, 35 },
|
||||
[DEX_AREA_THREE_ISLAND] = { MARKER_CIRCULAR, 14, 52 },
|
||||
[DEX_AREA_FOUR_ISLAND] = { MARKER_CIRCULAR, 12, 84 },
|
||||
[DEX_AREA_FIVE_ISLAND] = { MARKER_CIRCULAR, 45, 81 },
|
||||
[DEX_AREA_SIX_ISLAND] = { MARKER_CIRCULAR, 76, 84 },
|
||||
[DEX_AREA_SEVEN_ISLAND] = { MARKER_CIRCULAR, 104, 82 },
|
||||
[DEX_AREA_KINDLE_ROAD] = { MARKER_SMALL_V, 14, 2 },
|
||||
[DEX_AREA_TREASURE_BEACH] = { MARKER_CIRCULAR, 10, 15 },
|
||||
[DEX_AREA_CAPE_BRINK] = { MARKER_CIRCULAR, 12, 29 },
|
||||
[DEX_AREA_BOND_BRIDGE] = { MARKER_SMALL_H, 2, 52 },
|
||||
[DEX_AREA_THREE_ISLE_PATH] = { MARKER_SMALL_H, 12, 56 },
|
||||
[DEX_AREA_RESORT_GORGEOUS] = { MARKER_SMALL_H, 44, 74 },
|
||||
[DEX_AREA_WATER_LABYRINTH] = { MARKER_SMALL_H, 36, 78 },
|
||||
[DEX_AREA_FIVE_ISLE_MEADOW] = { MARKER_SMALL_V, 48, 80 },
|
||||
[DEX_AREA_MEMORIAL_PILLAR] = { MARKER_SMALL_V, 52, 86 },
|
||||
[DEX_AREA_OUTCAST_ISLAND] = { MARKER_CIRCULAR, 72, 74 },
|
||||
[DEX_AREA_GREEN_PATH] = { MARKER_SMALL_H, 72, 78 },
|
||||
[DEX_AREA_WATER_PATH] = { MARKER_SMALL_V, 81, 80 },
|
||||
[DEX_AREA_RUIN_VALLEY] = { MARKER_CIRCULAR, 76, 92 },
|
||||
[DEX_AREA_TRAINER_TOWER] = { MARKER_CIRCULAR, 104, 75 },
|
||||
[DEX_AREA_CANYON_ENTRANCE] = { MARKER_CIRCULAR, 104, 86 },
|
||||
[DEX_AREA_SEVAULT_CANYON] = { MARKER_SMALL_V, 108, 83 },
|
||||
[DEX_AREA_TANOBY_RUINS] = { MARKER_MED_H, 96, 90 },
|
||||
[DEX_AREA_MT_EMBER] = { MARKER_CIRCULAR, 14, 1 },
|
||||
[DEX_AREA_BERRY_FOREST] = { MARKER_CIRCULAR, 5, 52 },
|
||||
[DEX_AREA_ICEFALL_CAVE] = { MARKER_CIRCULAR, 13, 80 },
|
||||
[DEX_AREA_LOST_CAVE] = { MARKER_CIRCULAR, 54, 74 },
|
||||
[DEX_AREA_ALTERING_CAVE] = { MARKER_CIRCULAR, 69, 73 },
|
||||
[DEX_AREA_PATTERN_BUSH] = { MARKER_CIRCULAR, 76, 77 },
|
||||
[DEX_AREA_DOTTED_HOLE] = { MARKER_CIRCULAR, 73, 95 },
|
||||
[DEX_AREA_TANOBY_CHAMBER] = { MARKER_MED_H, 96, 90 },
|
||||
};
|
||||
|
||||
static void Task_ShowAreaMarkers(u8 taskId)
|
||||
{
|
||||
struct PAM_TaskData * data = (void *)gTasks[taskId].data;
|
||||
gSprites[data->spr_id].invisible = FALSE;
|
||||
gSprites[data->spriteId].invisible = FALSE;
|
||||
}
|
||||
|
||||
u8 Ctor_PokedexAreaMarkers(u16 species, u16 tilesTag, u8 palIdx, u8 y)
|
||||
u8 CreatePokedexAreaMarkers(u16 species, u16 tilesTag, u8 palIdx, u8 y)
|
||||
{
|
||||
struct SpriteTemplate spriteTemplate;
|
||||
struct CompressedSpriteSheet spriteSheet;
|
||||
@@ -165,34 +196,42 @@ u8 Ctor_PokedexAreaMarkers(u16 species, u16 tilesTag, u8 palIdx, u8 y)
|
||||
struct PAM_TaskData * data;
|
||||
struct Subsprite * subsprites;
|
||||
|
||||
// Load gfx
|
||||
spriteSheet.data = sMarkerTiles;
|
||||
spriteSheet.size = 0x4A0;
|
||||
spriteSheet.tag = tilesTag;
|
||||
LoadCompressedSpriteSheet(&spriteSheet);
|
||||
LoadPalette(sMarkerPal, 0x100 + 16 * palIdx, 0x20);
|
||||
|
||||
// Get marker subsprites
|
||||
taskId = CreateTask(Task_ShowAreaMarkers, 0);
|
||||
data = (void *)gTasks[taskId].data;
|
||||
data->unk_0C = 0;
|
||||
data->unused = 0;
|
||||
data->tilesTag = tilesTag;
|
||||
data->unk_10 = 0xFFFF;
|
||||
data->paletteTag = TAG_NONE;
|
||||
subsprites = Alloc(120 * sizeof(struct Subsprite));
|
||||
data->buffer = subsprites;
|
||||
data->subsprites.subsprites = subsprites;
|
||||
data->subsprites.subspriteCount = BuildPokedexAreaSubspriteBuffer(species, subsprites);
|
||||
data->subsprites.subspriteCount = GetSpeciesPokedexAreaMarkers(species, subsprites);
|
||||
|
||||
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
|
||||
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_BD);
|
||||
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(12, 8));
|
||||
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||||
SetGpuReg(REG_OFFSET_WININ, 0x1F1F);
|
||||
SetGpuReg(REG_OFFSET_WINOUT, 0x2F3D);
|
||||
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ);
|
||||
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_CLR);
|
||||
|
||||
// Set marker subsprites on full sprite
|
||||
spriteTemplate = gDummySpriteTemplate;
|
||||
spriteTemplate.tileTag = tilesTag;
|
||||
data->spr_id = CreateSprite(&spriteTemplate, 104, y + 32, 0);
|
||||
SetSubspriteTables(&gSprites[data->spr_id], &data->subsprites);
|
||||
gSprites[data->spr_id].oam.objMode = ST_OAM_OBJ_WINDOW;
|
||||
gSprites[data->spr_id].oam.paletteNum = palIdx;
|
||||
gSprites[data->spr_id].subspriteTableNum = 0;
|
||||
gSprites[data->spr_id].invisible = TRUE;
|
||||
data->spriteId = CreateSprite(&spriteTemplate, 104, y + 32, 0);
|
||||
SetSubspriteTables(&gSprites[data->spriteId], &data->subsprites);
|
||||
gSprites[data->spriteId].oam.objMode = ST_OAM_OBJ_WINDOW;
|
||||
gSprites[data->spriteId].oam.paletteNum = palIdx;
|
||||
gSprites[data->spriteId].subspriteTableNum = 0;
|
||||
gSprites[data->spriteId].invisible = TRUE;
|
||||
|
||||
// Show markers
|
||||
HideBg(1);
|
||||
SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0);
|
||||
FillBgTilemapBufferRect_Palette0(1, 0x00F, 0, 0, 30, 20);
|
||||
@@ -201,17 +240,17 @@ u8 Ctor_PokedexAreaMarkers(u16 species, u16 tilesTag, u8 palIdx, u8 y)
|
||||
return taskId;
|
||||
}
|
||||
|
||||
void Dtor_PokedexAreaMarkers(u8 taskId)
|
||||
void DestroyPokedexAreaMarkers(u8 taskId)
|
||||
{
|
||||
struct PAM_TaskData * data = (void *)gTasks[taskId].data;
|
||||
FreeSpriteTilesByTag(data->tilesTag);
|
||||
DestroySprite(&gSprites[data->spr_id]);
|
||||
DestroySprite(&gSprites[data->spriteId]);
|
||||
Free(data->buffer);
|
||||
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||||
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||||
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||||
SetGpuReg(REG_OFFSET_WININ, 0x1F1F);
|
||||
SetGpuReg(REG_OFFSET_WINOUT, 0x1F1F);
|
||||
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ);
|
||||
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ);
|
||||
ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
|
||||
HideBg(1);
|
||||
SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 2);
|
||||
@@ -221,14 +260,14 @@ void Dtor_PokedexAreaMarkers(u8 taskId)
|
||||
DestroyTask(taskId);
|
||||
}
|
||||
|
||||
void SetAreaSubsprite(s32 i, s32 whichArea, struct Subsprite * subsprites)
|
||||
void GetAreaMarkerSubsprite(s32 i, s32 dexArea, struct Subsprite * subsprites)
|
||||
{
|
||||
subsprites[i] = *sSubsprites[sSubspriteLookupTable[whichArea][0]];
|
||||
subsprites[i].x = sSubspriteLookupTable[whichArea][1];
|
||||
subsprites[i].y = sSubspriteLookupTable[whichArea][2];
|
||||
subsprites[i] = *sSubsprites[sAreaMarkers[dexArea][0]];
|
||||
subsprites[i].x = sAreaMarkers[dexArea][1];
|
||||
subsprites[i].y = sAreaMarkers[dexArea][2];
|
||||
}
|
||||
|
||||
u8 PokedexAreaMarkers_Any(u8 taskId)
|
||||
u8 GetNumPokedexAreaMarkers(u8 taskId)
|
||||
{
|
||||
struct PAM_TaskData * data = (void *)gTasks[taskId].data;
|
||||
return data->subsprites.subspriteCount;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "pokedex_area_markers.h"
|
||||
#include "field_specials.h"
|
||||
|
||||
#define TAG_AREA_MARKERS 2001
|
||||
|
||||
enum TextMode {
|
||||
TEXT_LEFT,
|
||||
TEXT_CENTER,
|
||||
@@ -31,7 +33,8 @@ struct PokedexScreenData
|
||||
{
|
||||
u8 taskId;
|
||||
u8 state;
|
||||
u8 data[4];
|
||||
u8 data[2];
|
||||
u8 areaMarkersTaskId;
|
||||
u32 unlockedCategories;
|
||||
u32 modeSelectInput;
|
||||
u16 modeSelectItemsAbove;
|
||||
@@ -3123,9 +3126,10 @@ u8 DexScreen_DrawMonAreaPage(void)
|
||||
}
|
||||
|
||||
// Create the area markers
|
||||
sPokedexScreenData->data[2] = Ctor_PokedexAreaMarkers(species, 2001, 3, kantoMapVoff * 8);
|
||||
if (!(PokedexAreaMarkers_Any(sPokedexScreenData->data[2])))
|
||||
sPokedexScreenData->areaMarkersTaskId = CreatePokedexAreaMarkers(species, TAG_AREA_MARKERS, 3, kantoMapVoff * 8);
|
||||
if (GetNumPokedexAreaMarkers(sPokedexScreenData->areaMarkersTaskId) == 0)
|
||||
{
|
||||
// No markers, display "Area Unknown"
|
||||
BlitBitmapRectToWindow(sPokedexScreenData->windowIds[0], (void *)sBlitTiles_WideEllipse, 0, 0, 88, 16, 4, 28, 88, 16);
|
||||
{
|
||||
s32 strWidth = GetStringWidth(FONT_SMALL, gText_AreaUnknown, 0);
|
||||
@@ -3149,7 +3153,7 @@ u8 DexScreen_DestroyAreaScreenResources(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
Dtor_PokedexAreaMarkers(sPokedexScreenData->data[2]);
|
||||
DestroyPokedexAreaMarkers(sPokedexScreenData->areaMarkersTaskId);
|
||||
|
||||
for (i = 0; i < 13; i++)
|
||||
DexScreen_RemoveWindow(&sPokedexScreenData->windowIds[i]);
|
||||
|
||||
+2
-2
@@ -2,12 +2,12 @@
|
||||
#include "script.h"
|
||||
#include "event_data.h"
|
||||
#include "quest_log.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "constants/maps.h"
|
||||
#include "constants/map_scripts.h"
|
||||
|
||||
extern void ResetContextNpcTextColor(void); // field_specials
|
||||
extern u16 CalcCRC16WithTable(u8 *data, int length); // util
|
||||
extern bool32 ValidateReceivedWonderCard(void); // mevent
|
||||
|
||||
#define RAM_SCRIPT_MAGIC 51
|
||||
|
||||
@@ -554,7 +554,7 @@ bool32 ValidateRamScript(void)
|
||||
u8 *GetSavedRamScriptIfValid(void)
|
||||
{
|
||||
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
|
||||
if (!ValidateReceivedWonderCard())
|
||||
if (!ValidateSavedWonderCard())
|
||||
return NULL;
|
||||
if (scriptData->magic != RAM_SCRIPT_MAGIC)
|
||||
return NULL;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include "trade.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "graphics.h"
|
||||
#include "strings.h"
|
||||
#include "menu.h"
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
#include "list_menu.h"
|
||||
#include "load_save.h"
|
||||
#include "menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "overworld.h"
|
||||
|
||||
+14
-13
@@ -1,6 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mevent_server.h"
|
||||
#include "mystery_gift_server.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "constants/union_room.h"
|
||||
|
||||
ALIGNED(4) const u8 gText_UR_EmptyString[] = _("");
|
||||
@@ -558,18 +559,18 @@ const u8 *const gTexts_UR_GladToMeetYou[GENDER_COUNT] = {
|
||||
ALIGNED(4) const u8 gText_UR_FinishedCheckingPlayersTrainerCard[] = _("Finished checking {SPECIAL_F7 0x01}'s\nTRAINER CARD.{PAUSE 60}");
|
||||
ALIGNED(4) static const u8 sText_CanceledReadingCard[] = _("Canceled reading the Card.");
|
||||
|
||||
static const struct mevent_client_cmd sClientScript_DynamicError[] = {
|
||||
CLI_RECEIVE(0x15),
|
||||
CLI_RECVBUF,
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0e)
|
||||
static const struct MysteryGiftClientCmd sClientScript_DynamicError[] = {
|
||||
{CLI_RECV, MG_LINKID_DYNAMIC_MSG},
|
||||
{CLI_COPY_MSG},
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_BUFFER_FAILURE}
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gServerScript_ClientCanceledCard[] = {
|
||||
SRV_SEND(0x20, sClientScript_DynamicError),
|
||||
SRV_WAITSND,
|
||||
SRV_SENDSTR(0x1b, sText_CanceledReadingCard),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x09)
|
||||
const struct MysteryGiftServerCmd gServerScript_ClientCanceledCard[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_DynamicError)},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_MSG, PTR_ARG(sText_CanceledReadingCard)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CLIENT_CANCELED}
|
||||
};
|
||||
|
||||
@@ -186,7 +186,7 @@ static u16 GetCurrentMapWildMonHeaderId(void)
|
||||
gSaveBlock1Ptr->location.mapNum == MAP_NUM(SIX_ISLAND_ALTERING_CAVE))
|
||||
{
|
||||
u16 alteringCaveId = VarGet(VAR_ALTERING_CAVE_WILD_SET);
|
||||
if (alteringCaveId > 8)
|
||||
if (alteringCaveId >= NUM_ALTERING_CAVE_TABLES)
|
||||
alteringCaveId = 0;
|
||||
|
||||
i += alteringCaveId;
|
||||
|
||||
+164
-154
@@ -4,16 +4,11 @@
|
||||
#include "wild_encounter.h"
|
||||
#include "roamer.h"
|
||||
#include "overworld.h"
|
||||
#include "pokedex.h"
|
||||
#include "pokedex_area_markers.h"
|
||||
#include "constants/region_map_sections.h"
|
||||
#include "constants/maps.h"
|
||||
|
||||
struct SeviiDexArea
|
||||
{
|
||||
const u16 (*lut)[2];
|
||||
s32 count;
|
||||
};
|
||||
|
||||
struct RoamerPair
|
||||
{
|
||||
u16 roamer;
|
||||
@@ -21,137 +16,141 @@ struct RoamerPair
|
||||
};
|
||||
|
||||
static s32 GetRoamerIndex(u16 species);
|
||||
static s32 CountRoamerNests(u16 species, struct Subsprite * subsprites);
|
||||
static bool32 PokemonInAnyEncounterTableInMap(const struct WildPokemonHeader * data, s32 species);
|
||||
static bool32 PokemonInEncounterTable(const struct WildPokemonInfo * pokemon, s32 species, s32 count);
|
||||
static s32 GetRoamerPokedexAreaMarkers(u16 species, struct Subsprite * subsprites);
|
||||
static bool32 IsSpeciesOnMap(const struct WildPokemonHeader * data, s32 species);
|
||||
static bool32 IsSpeciesInEncounterTable(const struct WildPokemonInfo * pokemon, s32 species, s32 count);
|
||||
static u16 GetMapSecIdFromWildMonHeader(const struct WildPokemonHeader * header);
|
||||
static bool32 TryGetMapSecPokedexAreaEntry(u16 mapSecId, const u16 (*lut)[2], s32 count, s32 * lutIdx_p, u16 * tableIdx_p);
|
||||
static bool32 FindDexAreaByMapSec(u16 mapSecId, const u16 (*lut)[2], s32 count, s32 * lutIdx_p, u16 * tableIdx_p);
|
||||
|
||||
static const u16 sDexAreas_Kanto[][2] = {
|
||||
{ MAPSEC_PALLET_TOWN, 1 },
|
||||
{ MAPSEC_VIRIDIAN_CITY, 2 },
|
||||
{ MAPSEC_PEWTER_CITY, 3 },
|
||||
{ MAPSEC_CERULEAN_CITY, 4 },
|
||||
{ MAPSEC_LAVENDER_TOWN, 5 },
|
||||
{ MAPSEC_VERMILION_CITY, 6 },
|
||||
{ MAPSEC_CELADON_CITY, 7 },
|
||||
{ MAPSEC_FUCHSIA_CITY, 8 },
|
||||
{ MAPSEC_CINNABAR_ISLAND, 9 },
|
||||
{ MAPSEC_INDIGO_PLATEAU, 10 },
|
||||
{ MAPSEC_SAFFRON_CITY, 11 },
|
||||
{ MAPSEC_ROUTE_4_POKECENTER, 15 },
|
||||
{ MAPSEC_ROUTE_10_POKECENTER, 21 },
|
||||
{ MAPSEC_ROUTE_1, 12 },
|
||||
{ MAPSEC_ROUTE_2, 13 },
|
||||
{ MAPSEC_ROUTE_3, 14 },
|
||||
{ MAPSEC_ROUTE_4, 15 },
|
||||
{ MAPSEC_ROUTE_5, 16 },
|
||||
{ MAPSEC_ROUTE_6, 17 },
|
||||
{ MAPSEC_ROUTE_7, 18 },
|
||||
{ MAPSEC_ROUTE_8, 19 },
|
||||
{ MAPSEC_ROUTE_9, 20 },
|
||||
{ MAPSEC_ROUTE_10, 21 },
|
||||
{ MAPSEC_ROUTE_11, 22 },
|
||||
{ MAPSEC_ROUTE_12, 23 },
|
||||
{ MAPSEC_ROUTE_13, 24 },
|
||||
{ MAPSEC_ROUTE_14, 25 },
|
||||
{ MAPSEC_ROUTE_15, 26 },
|
||||
{ MAPSEC_ROUTE_16, 27 },
|
||||
{ MAPSEC_ROUTE_17, 28 },
|
||||
{ MAPSEC_ROUTE_18, 29 },
|
||||
{ MAPSEC_ROUTE_19, 30 },
|
||||
{ MAPSEC_ROUTE_20, 31 },
|
||||
{ MAPSEC_ROUTE_21, 32 },
|
||||
{ MAPSEC_ROUTE_22, 33 },
|
||||
{ MAPSEC_ROUTE_23, 34 },
|
||||
{ MAPSEC_ROUTE_24, 35 },
|
||||
{ MAPSEC_ROUTE_25, 36 },
|
||||
{ MAPSEC_VIRIDIAN_FOREST, 37 },
|
||||
{ MAPSEC_MT_MOON, 39 },
|
||||
{ MAPSEC_S_S_ANNE, 6 },
|
||||
{ MAPSEC_UNDERGROUND_PATH, 11 },
|
||||
{ MAPSEC_UNDERGROUND_PATH_2, 11 },
|
||||
{ MAPSEC_DIGLETTS_CAVE, 38 },
|
||||
{ MAPSEC_KANTO_VICTORY_ROAD, 47 },
|
||||
{ MAPSEC_ROCKET_HIDEOUT, 7 },
|
||||
{ MAPSEC_SILPH_CO, 11 },
|
||||
{ MAPSEC_POKEMON_MANSION, 46 },
|
||||
{ MAPSEC_KANTO_SAFARI_ZONE, 44 },
|
||||
{ MAPSEC_POKEMON_LEAGUE, 47 },
|
||||
{ MAPSEC_ROCK_TUNNEL, 41 },
|
||||
{ MAPSEC_SEAFOAM_ISLANDS, 45 },
|
||||
{ MAPSEC_POKEMON_TOWER, 43 },
|
||||
{ MAPSEC_CERULEAN_CAVE, 40 },
|
||||
{ MAPSEC_POWER_PLANT, 42 }
|
||||
{ MAPSEC_PALLET_TOWN, DEX_AREA_PALLET_TOWN },
|
||||
{ MAPSEC_VIRIDIAN_CITY, DEX_AREA_VIRIDIAN_CITY },
|
||||
{ MAPSEC_PEWTER_CITY, DEX_AREA_PEWTER_CITY },
|
||||
{ MAPSEC_CERULEAN_CITY, DEX_AREA_CERULEAN_CITY },
|
||||
{ MAPSEC_LAVENDER_TOWN, DEX_AREA_LAVENDER_TOWN },
|
||||
{ MAPSEC_VERMILION_CITY, DEX_AREA_VERMILION_CITY },
|
||||
{ MAPSEC_CELADON_CITY, DEX_AREA_CELADON_CITY },
|
||||
{ MAPSEC_FUCHSIA_CITY, DEX_AREA_FUCHSIA_CITY },
|
||||
{ MAPSEC_CINNABAR_ISLAND, DEX_AREA_CINNABAR_ISLAND },
|
||||
{ MAPSEC_INDIGO_PLATEAU, DEX_AREA_INDIGO_PLATEAU },
|
||||
{ MAPSEC_SAFFRON_CITY, DEX_AREA_SAFFRON_CITY },
|
||||
{ MAPSEC_ROUTE_4_POKECENTER, DEX_AREA_ROUTE_4 },
|
||||
{ MAPSEC_ROUTE_10_POKECENTER, DEX_AREA_ROUTE_10 },
|
||||
{ MAPSEC_ROUTE_1, DEX_AREA_ROUTE_1 },
|
||||
{ MAPSEC_ROUTE_2, DEX_AREA_ROUTE_2 },
|
||||
{ MAPSEC_ROUTE_3, DEX_AREA_ROUTE_3 },
|
||||
{ MAPSEC_ROUTE_4, DEX_AREA_ROUTE_4 },
|
||||
{ MAPSEC_ROUTE_5, DEX_AREA_ROUTE_5 },
|
||||
{ MAPSEC_ROUTE_6, DEX_AREA_ROUTE_6 },
|
||||
{ MAPSEC_ROUTE_7, DEX_AREA_ROUTE_7 },
|
||||
{ MAPSEC_ROUTE_8, DEX_AREA_ROUTE_8 },
|
||||
{ MAPSEC_ROUTE_9, DEX_AREA_ROUTE_9 },
|
||||
{ MAPSEC_ROUTE_10, DEX_AREA_ROUTE_10 },
|
||||
{ MAPSEC_ROUTE_11, DEX_AREA_ROUTE_11 },
|
||||
{ MAPSEC_ROUTE_12, DEX_AREA_ROUTE_12 },
|
||||
{ MAPSEC_ROUTE_13, DEX_AREA_ROUTE_13 },
|
||||
{ MAPSEC_ROUTE_14, DEX_AREA_ROUTE_14 },
|
||||
{ MAPSEC_ROUTE_15, DEX_AREA_ROUTE_15 },
|
||||
{ MAPSEC_ROUTE_16, DEX_AREA_ROUTE_16 },
|
||||
{ MAPSEC_ROUTE_17, DEX_AREA_ROUTE_17 },
|
||||
{ MAPSEC_ROUTE_18, DEX_AREA_ROUTE_18 },
|
||||
{ MAPSEC_ROUTE_19, DEX_AREA_ROUTE_19 },
|
||||
{ MAPSEC_ROUTE_20, DEX_AREA_ROUTE_20 },
|
||||
{ MAPSEC_ROUTE_21, DEX_AREA_ROUTE_21 },
|
||||
{ MAPSEC_ROUTE_22, DEX_AREA_ROUTE_22 },
|
||||
{ MAPSEC_ROUTE_23, DEX_AREA_ROUTE_23 },
|
||||
{ MAPSEC_ROUTE_24, DEX_AREA_ROUTE_24 },
|
||||
{ MAPSEC_ROUTE_25, DEX_AREA_ROUTE_25 },
|
||||
{ MAPSEC_VIRIDIAN_FOREST, DEX_AREA_VIRIDIAN_FOREST },
|
||||
{ MAPSEC_MT_MOON, DEX_AREA_MT_MOON },
|
||||
{ MAPSEC_S_S_ANNE, DEX_AREA_VERMILION_CITY },
|
||||
{ MAPSEC_UNDERGROUND_PATH, DEX_AREA_SAFFRON_CITY },
|
||||
{ MAPSEC_UNDERGROUND_PATH_2, DEX_AREA_SAFFRON_CITY },
|
||||
{ MAPSEC_DIGLETTS_CAVE, DEX_AREA_DIGLETTS_CAVE },
|
||||
{ MAPSEC_KANTO_VICTORY_ROAD, DEX_AREA_VICTORY_ROAD },
|
||||
{ MAPSEC_ROCKET_HIDEOUT, DEX_AREA_CELADON_CITY },
|
||||
{ MAPSEC_SILPH_CO, DEX_AREA_SAFFRON_CITY },
|
||||
{ MAPSEC_POKEMON_MANSION, DEX_AREA_POKEMON_MANSION },
|
||||
{ MAPSEC_KANTO_SAFARI_ZONE, DEX_AREA_SAFARI_ZONE },
|
||||
{ MAPSEC_POKEMON_LEAGUE, DEX_AREA_VICTORY_ROAD },
|
||||
{ MAPSEC_ROCK_TUNNEL, DEX_AREA_ROCK_TUNNEL },
|
||||
{ MAPSEC_SEAFOAM_ISLANDS, DEX_AREA_SEAFOAM_ISLANDS },
|
||||
{ MAPSEC_POKEMON_TOWER, DEX_AREA_POKEMON_TOWER },
|
||||
{ MAPSEC_CERULEAN_CAVE, DEX_AREA_CERULEAN_CAVE },
|
||||
{ MAPSEC_POWER_PLANT, DEX_AREA_POWER_PLANT }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii1[][2] = {
|
||||
{ MAPSEC_KINDLE_ROAD, 55 },
|
||||
{ MAPSEC_TREASURE_BEACH, 56 },
|
||||
{ MAPSEC_ONE_ISLAND, 48 },
|
||||
{ MAPSEC_MT_EMBER, 72 }
|
||||
{ MAPSEC_KINDLE_ROAD, DEX_AREA_KINDLE_ROAD },
|
||||
{ MAPSEC_TREASURE_BEACH, DEX_AREA_TREASURE_BEACH },
|
||||
{ MAPSEC_ONE_ISLAND, DEX_AREA_ONE_ISLAND },
|
||||
{ MAPSEC_MT_EMBER, DEX_AREA_MT_EMBER }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii2[][2] = {
|
||||
{ MAPSEC_CAPE_BRINK, 57 },
|
||||
{ MAPSEC_TWO_ISLAND, 49 }
|
||||
{ MAPSEC_CAPE_BRINK, DEX_AREA_CAPE_BRINK },
|
||||
{ MAPSEC_TWO_ISLAND, DEX_AREA_TWO_ISLAND }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii3[][2] = {
|
||||
{ MAPSEC_BOND_BRIDGE, 58 },
|
||||
{ MAPSEC_THREE_ISLE_PORT, 59 },
|
||||
{ MAPSEC_THREE_ISLAND, 50 },
|
||||
{ MAPSEC_BERRY_FOREST, 73 },
|
||||
{ MAPSEC_THREE_ISLE_PATH, 59 }
|
||||
{ MAPSEC_BOND_BRIDGE, DEX_AREA_BOND_BRIDGE },
|
||||
{ MAPSEC_THREE_ISLE_PORT, DEX_AREA_THREE_ISLE_PATH },
|
||||
{ MAPSEC_THREE_ISLAND, DEX_AREA_THREE_ISLAND },
|
||||
{ MAPSEC_BERRY_FOREST, DEX_AREA_BERRY_FOREST },
|
||||
{ MAPSEC_THREE_ISLE_PATH, DEX_AREA_THREE_ISLE_PATH }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii4[][2] = {
|
||||
{ MAPSEC_FOUR_ISLAND, 51 },
|
||||
{ MAPSEC_ICEFALL_CAVE, 74 }
|
||||
{ MAPSEC_FOUR_ISLAND, DEX_AREA_FOUR_ISLAND },
|
||||
{ MAPSEC_ICEFALL_CAVE, DEX_AREA_ICEFALL_CAVE }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii5[][2] = {
|
||||
{ MAPSEC_RESORT_GORGEOUS, 60 },
|
||||
{ MAPSEC_WATER_LABYRINTH, 61 },
|
||||
{ MAPSEC_FIVE_ISLE_MEADOW, 62 },
|
||||
{ MAPSEC_MEMORIAL_PILLAR, 63 },
|
||||
{ MAPSEC_FIVE_ISLAND, 52 },
|
||||
{ MAPSEC_ROCKET_WAREHOUSE, 62 },
|
||||
{ MAPSEC_LOST_CAVE, 75 }
|
||||
{ MAPSEC_RESORT_GORGEOUS, DEX_AREA_RESORT_GORGEOUS },
|
||||
{ MAPSEC_WATER_LABYRINTH, DEX_AREA_WATER_LABYRINTH },
|
||||
{ MAPSEC_FIVE_ISLE_MEADOW, DEX_AREA_FIVE_ISLE_MEADOW },
|
||||
{ MAPSEC_MEMORIAL_PILLAR, DEX_AREA_MEMORIAL_PILLAR },
|
||||
{ MAPSEC_FIVE_ISLAND, DEX_AREA_FIVE_ISLAND },
|
||||
{ MAPSEC_ROCKET_WAREHOUSE, DEX_AREA_FIVE_ISLE_MEADOW },
|
||||
{ MAPSEC_LOST_CAVE, DEX_AREA_LOST_CAVE }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii6[][2] = {
|
||||
{ MAPSEC_OUTCAST_ISLAND, 64 },
|
||||
{ MAPSEC_GREEN_PATH, 65 },
|
||||
{ MAPSEC_WATER_PATH, 66 },
|
||||
{ MAPSEC_RUIN_VALLEY, 67 },
|
||||
{ MAPSEC_DOTTED_HOLE, 78 },
|
||||
{ MAPSEC_PATTERN_BUSH, 77 },
|
||||
{ MAPSEC_ALTERING_CAVE, 76 }
|
||||
{ MAPSEC_OUTCAST_ISLAND, DEX_AREA_OUTCAST_ISLAND },
|
||||
{ MAPSEC_GREEN_PATH, DEX_AREA_GREEN_PATH },
|
||||
{ MAPSEC_WATER_PATH, DEX_AREA_WATER_PATH },
|
||||
{ MAPSEC_RUIN_VALLEY, DEX_AREA_RUIN_VALLEY },
|
||||
{ MAPSEC_DOTTED_HOLE, DEX_AREA_DOTTED_HOLE },
|
||||
{ MAPSEC_PATTERN_BUSH, DEX_AREA_PATTERN_BUSH },
|
||||
{ MAPSEC_ALTERING_CAVE, DEX_AREA_ALTERING_CAVE }
|
||||
};
|
||||
|
||||
static const u16 sDexAreas_Sevii7[][2] = {
|
||||
{ MAPSEC_TRAINER_TOWER, 68 },
|
||||
{ MAPSEC_CANYON_ENTRANCE, 69 },
|
||||
{ MAPSEC_SEVAULT_CANYON, 70 },
|
||||
{ MAPSEC_TANOBY_RUINS, 71 },
|
||||
{ MAPSEC_MONEAN_CHAMBER, 79 },
|
||||
{ MAPSEC_LIPTOO_CHAMBER, 79 },
|
||||
{ MAPSEC_WEEPTH_CHAMBER, 79 },
|
||||
{ MAPSEC_DILFORD_CHAMBER, 79 },
|
||||
{ MAPSEC_SCUFIB_CHAMBER, 79 },
|
||||
{ MAPSEC_RIXY_CHAMBER, 79 },
|
||||
{ MAPSEC_VIAPOIS_CHAMBER, 79 }
|
||||
{ MAPSEC_TRAINER_TOWER, DEX_AREA_TRAINER_TOWER },
|
||||
{ MAPSEC_CANYON_ENTRANCE, DEX_AREA_CANYON_ENTRANCE },
|
||||
{ MAPSEC_SEVAULT_CANYON, DEX_AREA_SEVAULT_CANYON },
|
||||
{ MAPSEC_TANOBY_RUINS, DEX_AREA_TANOBY_RUINS },
|
||||
{ MAPSEC_MONEAN_CHAMBER, DEX_AREA_TANOBY_CHAMBER },
|
||||
{ MAPSEC_LIPTOO_CHAMBER, DEX_AREA_TANOBY_CHAMBER },
|
||||
{ MAPSEC_WEEPTH_CHAMBER, DEX_AREA_TANOBY_CHAMBER },
|
||||
{ MAPSEC_DILFORD_CHAMBER, DEX_AREA_TANOBY_CHAMBER },
|
||||
{ MAPSEC_SCUFIB_CHAMBER, DEX_AREA_TANOBY_CHAMBER },
|
||||
{ MAPSEC_RIXY_CHAMBER, DEX_AREA_TANOBY_CHAMBER },
|
||||
{ MAPSEC_VIAPOIS_CHAMBER, DEX_AREA_TANOBY_CHAMBER }
|
||||
};
|
||||
|
||||
static const struct SeviiDexArea sSeviiDexAreas[] = {
|
||||
{ sDexAreas_Sevii1, 4 },
|
||||
{ sDexAreas_Sevii2, 2 },
|
||||
{ sDexAreas_Sevii3, 5 },
|
||||
{ sDexAreas_Sevii4, 2 },
|
||||
{ sDexAreas_Sevii5, 7 },
|
||||
{ sDexAreas_Sevii6, 7 },
|
||||
{ sDexAreas_Sevii7, 11 }
|
||||
static const struct
|
||||
{
|
||||
const u16 (*table)[2];
|
||||
s32 count;
|
||||
} sSeviiDexAreas[] = {
|
||||
{ sDexAreas_Sevii1, ARRAY_COUNT(sDexAreas_Sevii1) },
|
||||
{ sDexAreas_Sevii2, ARRAY_COUNT(sDexAreas_Sevii2) },
|
||||
{ sDexAreas_Sevii3, ARRAY_COUNT(sDexAreas_Sevii3) },
|
||||
{ sDexAreas_Sevii4, ARRAY_COUNT(sDexAreas_Sevii4) },
|
||||
{ sDexAreas_Sevii5, ARRAY_COUNT(sDexAreas_Sevii5) },
|
||||
{ sDexAreas_Sevii6, ARRAY_COUNT(sDexAreas_Sevii6) },
|
||||
{ sDexAreas_Sevii7, ARRAY_COUNT(sDexAreas_Sevii7) }
|
||||
};
|
||||
|
||||
static const struct RoamerPair sRoamerPairs[] = {
|
||||
@@ -160,27 +159,27 @@ static const struct RoamerPair sRoamerPairs[] = {
|
||||
{ SPECIES_RAIKOU, SPECIES_SQUIRTLE }
|
||||
};
|
||||
|
||||
s32 BuildPokedexAreaSubspriteBuffer(u16 species, struct Subsprite * subsprites)
|
||||
// Scans for the given species and populates 'subsprites' with the area markers.
|
||||
// Returns the number of areas where the species was found.
|
||||
s32 GetSpeciesPokedexAreaMarkers(u16 species, struct Subsprite * subsprites)
|
||||
{
|
||||
s32 areaCount;
|
||||
s32 j;
|
||||
s32 mapSecId;
|
||||
u16 dexAreaSubspriteIdx;
|
||||
s32 dexAreaEntryLUTidx;
|
||||
u16 dexArea;
|
||||
s32 tableIndex;
|
||||
s32 seviiAreas;
|
||||
s32 alteringCaveCount;
|
||||
s32 alteringCaveNum;
|
||||
s32 i;
|
||||
|
||||
if (GetRoamerIndex(species) >= SPECIES_NONE)
|
||||
{
|
||||
return CountRoamerNests(species, subsprites);
|
||||
}
|
||||
if (GetRoamerIndex(species) >= 0)
|
||||
return GetRoamerPokedexAreaMarkers(species, subsprites);
|
||||
|
||||
seviiAreas = GetUnlockedSeviiAreas();
|
||||
alteringCaveCount = 0;
|
||||
alteringCaveNum = VarGet(VAR_ALTERING_CAVE_WILD_SET);
|
||||
if (alteringCaveNum > 8)
|
||||
if (alteringCaveNum >= NUM_ALTERING_CAVE_TABLES)
|
||||
alteringCaveNum = 0;
|
||||
for (i = 0, areaCount = 0; gWildMonHeaders[i].mapGroup != MAP_GROUP(UNDEFINED); i++)
|
||||
{
|
||||
@@ -191,27 +190,27 @@ s32 BuildPokedexAreaSubspriteBuffer(u16 species, struct Subsprite * subsprites)
|
||||
if (alteringCaveNum != alteringCaveCount - 1)
|
||||
continue;
|
||||
}
|
||||
if (PokemonInAnyEncounterTableInMap(&gWildMonHeaders[i], species))
|
||||
if (IsSpeciesOnMap(&gWildMonHeaders[i], species))
|
||||
{
|
||||
dexAreaEntryLUTidx = 0;
|
||||
while (TryGetMapSecPokedexAreaEntry(mapSecId, sDexAreas_Kanto, 55, &dexAreaEntryLUTidx, &dexAreaSubspriteIdx))
|
||||
// Search for all dex areas associated with this MAPSEC.
|
||||
// In the vanilla game each MAPSEC only has at most one DEX_AREA.
|
||||
tableIndex = 0;
|
||||
while (FindDexAreaByMapSec(mapSecId, sDexAreas_Kanto, ARRAY_COUNT(sDexAreas_Kanto), &tableIndex, &dexArea))
|
||||
{
|
||||
if (dexAreaSubspriteIdx != 0)
|
||||
{
|
||||
SetAreaSubsprite(areaCount++, dexAreaSubspriteIdx, subsprites);
|
||||
}
|
||||
if (dexArea != DEX_AREA_NONE)
|
||||
GetAreaMarkerSubsprite(areaCount++, dexArea, subsprites);
|
||||
}
|
||||
for (j = 0; j < NELEMS(sSeviiDexAreas); j++)
|
||||
|
||||
for (j = 0; j < ARRAY_COUNT(sSeviiDexAreas); j++)
|
||||
{
|
||||
if ((seviiAreas >> j) & 1)
|
||||
{
|
||||
dexAreaEntryLUTidx = 0;
|
||||
while (TryGetMapSecPokedexAreaEntry(mapSecId, sSeviiDexAreas[j].lut, sSeviiDexAreas[j].count, &dexAreaEntryLUTidx, &dexAreaSubspriteIdx))
|
||||
// Search for all dex areas associated with this MAPSEC in this unlocked Sevii Island
|
||||
tableIndex = 0;
|
||||
while (FindDexAreaByMapSec(mapSecId, sSeviiDexAreas[j].table, sSeviiDexAreas[j].count, &tableIndex, &dexArea))
|
||||
{
|
||||
if (dexAreaSubspriteIdx != 0)
|
||||
{
|
||||
SetAreaSubsprite(areaCount++, dexAreaSubspriteIdx, subsprites);
|
||||
}
|
||||
if (dexArea != DEX_AREA_NONE)
|
||||
GetAreaMarkerSubsprite(areaCount++, dexArea, subsprites);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +223,7 @@ s32 BuildPokedexAreaSubspriteBuffer(u16 species, struct Subsprite * subsprites)
|
||||
static s32 GetRoamerIndex(u16 species)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < NELEMS(sRoamerPairs); i++)
|
||||
for (i = 0; i < ARRAY_COUNT(sRoamerPairs); i++)
|
||||
{
|
||||
if (sRoamerPairs[i].roamer == species)
|
||||
return i;
|
||||
@@ -233,46 +232,54 @@ static s32 GetRoamerIndex(u16 species)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static s32 CountRoamerNests(u16 species, struct Subsprite * subsprites)
|
||||
static s32 GetRoamerPokedexAreaMarkers(u16 species, struct Subsprite * subsprites)
|
||||
{
|
||||
u16 roamerLocation;
|
||||
u16 mapSecId;
|
||||
s32 roamerIdx;
|
||||
u16 dexAreaSubspriteIdx;
|
||||
s32 dexAreaEntryLUTidx;
|
||||
u16 dexArea;
|
||||
s32 tableIndex;
|
||||
|
||||
// Make sure that this is a roamer species, and that it corresponds to the player's starter.
|
||||
roamerIdx = GetRoamerIndex(species);
|
||||
if (roamerIdx < 0)
|
||||
return 0;
|
||||
if (sRoamerPairs[roamerIdx].starter != GetStarterSpecies())
|
||||
return 0;
|
||||
roamerLocation = GetRoamerLocationMapSectionId();
|
||||
dexAreaEntryLUTidx = 0;
|
||||
if (TryGetMapSecPokedexAreaEntry(roamerLocation, sDexAreas_Kanto, 55, &dexAreaEntryLUTidx, &dexAreaSubspriteIdx))
|
||||
|
||||
mapSecId = GetRoamerLocationMapSectionId();
|
||||
tableIndex = 0;
|
||||
if (FindDexAreaByMapSec(mapSecId, sDexAreas_Kanto, ARRAY_COUNT(sDexAreas_Kanto), &tableIndex, &dexArea))
|
||||
{
|
||||
if (dexAreaSubspriteIdx != 0)
|
||||
if (dexArea != DEX_AREA_NONE)
|
||||
{
|
||||
SetAreaSubsprite(0, dexAreaSubspriteIdx, subsprites);
|
||||
GetAreaMarkerSubsprite(0, dexArea, subsprites);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool32 PokemonInAnyEncounterTableInMap(const struct WildPokemonHeader * data, s32 species)
|
||||
static bool32 IsSpeciesOnMap(const struct WildPokemonHeader * data, s32 species)
|
||||
{
|
||||
if (PokemonInEncounterTable(data->landMonsInfo, species, 12))
|
||||
if (IsSpeciesInEncounterTable(data->landMonsInfo, species, LAND_WILD_COUNT))
|
||||
return TRUE;
|
||||
if (PokemonInEncounterTable(data->waterMonsInfo, species, 5))
|
||||
if (IsSpeciesInEncounterTable(data->waterMonsInfo, species, WATER_WILD_COUNT))
|
||||
return TRUE;
|
||||
if (PokemonInEncounterTable(data->fishingMonsInfo, species, 12)) // 10
|
||||
// When searching the fishing encounters, this incorrectly uses the size of the land encounters.
|
||||
// As a result it's reading out of bounds of the fishing encounters tables.
|
||||
#ifdef BUGFIX
|
||||
if (IsSpeciesInEncounterTable(data->fishingMonsInfo, species, FISH_WILD_COUNT))
|
||||
#else
|
||||
if (IsSpeciesInEncounterTable(data->fishingMonsInfo, species, LAND_WILD_COUNT))
|
||||
#endif
|
||||
return TRUE;
|
||||
if (PokemonInEncounterTable(data->rockSmashMonsInfo, species, 5))
|
||||
if (IsSpeciesInEncounterTable(data->rockSmashMonsInfo, species, ROCK_WILD_COUNT))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 PokemonInEncounterTable(const struct WildPokemonInfo * info, s32 species, s32 count)
|
||||
static bool32 IsSpeciesInEncounterTable(const struct WildPokemonInfo * info, s32 species, s32 count)
|
||||
{
|
||||
s32 i;
|
||||
if (info != NULL)
|
||||
@@ -291,15 +298,18 @@ static u16 GetMapSecIdFromWildMonHeader(const struct WildPokemonHeader * header)
|
||||
return Overworld_GetMapHeaderByGroupAndId(header->mapGroup, header->mapNum)->regionMapSectionId;
|
||||
}
|
||||
|
||||
static bool32 TryGetMapSecPokedexAreaEntry(u16 mapSecId, const u16 (*lut)[2], s32 count, s32 * lutIdx_p, u16 * tableIdx_p)
|
||||
// Search a MAPSEC -> DEX_AREA table for the given mapsec.
|
||||
// Assigns the DEX_AREA (if found) to 'dexArea', and the first unread table index to 'index'.
|
||||
// Returns TRUE if DEX_AREA was found, FALSE otherwise.
|
||||
static bool32 FindDexAreaByMapSec(u16 mapSecId, const u16 (*table)[2], s32 count, s32 * index, u16 * dexArea)
|
||||
{
|
||||
s32 i;
|
||||
for (i = *lutIdx_p; i < count; i++)
|
||||
for (i = *index; i < count; i++)
|
||||
{
|
||||
if (lut[i][0] == mapSecId)
|
||||
if (table[i][0] == mapSecId)
|
||||
{
|
||||
*tableIdx_p = lut[i][1];
|
||||
*lutIdx_p = i + 1;
|
||||
*dexArea = table[i][1];
|
||||
*index = i + 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "global.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "random.h"
|
||||
#include "event_data.h"
|
||||
#include "wonder_news.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
// Every 4th reward for sending Wonder News to a link partner is a "big" reward.
|
||||
#define MAX_SENT_REWARD 4
|
||||
|
||||
// Only up to 5 rewards can be received in a short period. After this the player
|
||||
// must take 500 steps before any more rewards can be received.
|
||||
#define MAX_REWARD 5
|
||||
|
||||
static u32 GetRewardItem(struct WonderNewsMetadata *);
|
||||
static u32 GetRewardType(struct WonderNewsMetadata *);
|
||||
static void IncrementRewardCounter(struct WonderNewsMetadata *);
|
||||
static void IncrementSentRewardCounter(struct WonderNewsMetadata *);
|
||||
static void ResetSentRewardCounter(struct WonderNewsMetadata *);
|
||||
|
||||
void WonderNews_SetReward(u32 newsType)
|
||||
{
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
|
||||
data->newsType = newsType;
|
||||
switch (newsType)
|
||||
{
|
||||
case WONDER_NEWS_NONE:
|
||||
break;
|
||||
case WONDER_NEWS_RECV_FRIEND:
|
||||
case WONDER_NEWS_RECV_WIRELESS:
|
||||
// Random berry between ITEM_RAZZ_BERRY and ITEM_NOMEL_BERRY
|
||||
data->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_RAZZ_BERRY);
|
||||
break;
|
||||
case WONDER_NEWS_SENT:
|
||||
// Random berry between ITEM_CHERI_BERRY and ITEM_IAPAPA_BERRY
|
||||
data->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_CHERI_BERRY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WonderNews_Reset(void)
|
||||
{
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
|
||||
data->newsType = WONDER_NEWS_NONE;
|
||||
data->sentRewardCounter = 0;
|
||||
data->rewardCounter = 0;
|
||||
data->berry = 0;
|
||||
VarSet(VAR_WONDER_NEWS_STEP_COUNTER, 0);
|
||||
}
|
||||
|
||||
void WonderNews_IncrementStepCounter(void)
|
||||
{
|
||||
u16 *stepCounter = GetVarPointer(VAR_WONDER_NEWS_STEP_COUNTER);
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
|
||||
// If the player has reached the reward limit, start counting steps.
|
||||
// When they reach 500 steps reset the reward counter to allow them to
|
||||
// receive rewards again.
|
||||
if (data->rewardCounter >= MAX_REWARD && ++(*stepCounter) >= 500)
|
||||
{
|
||||
data->rewardCounter = 0;
|
||||
*stepCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u16 WonderNews_GetRewardInfo(void)
|
||||
{
|
||||
u16 *result = &gSpecialVar_Result;
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
u16 rewardType;
|
||||
|
||||
if (!IsMysteryGiftEnabled() || !ValidateSavedWonderNews())
|
||||
return NEWS_REWARD_NONE;
|
||||
|
||||
rewardType = GetRewardType(data);
|
||||
|
||||
switch (rewardType)
|
||||
{
|
||||
case NEWS_REWARD_RECV_SMALL:
|
||||
case NEWS_REWARD_RECV_BIG:
|
||||
*result = GetRewardItem(data);
|
||||
break;
|
||||
case NEWS_REWARD_SENT_SMALL:
|
||||
*result = GetRewardItem(data);
|
||||
IncrementSentRewardCounter(data);
|
||||
break;
|
||||
case NEWS_REWARD_SENT_BIG:
|
||||
*result = GetRewardItem(data);
|
||||
ResetSentRewardCounter(data);
|
||||
break;
|
||||
case NEWS_REWARD_NONE:
|
||||
case NEWS_REWARD_WAITING:
|
||||
case NEWS_REWARD_AT_MAX:
|
||||
break;
|
||||
}
|
||||
|
||||
return rewardType;
|
||||
}
|
||||
|
||||
static u32 GetRewardItem(struct WonderNewsMetadata *data)
|
||||
{
|
||||
u32 itemId;
|
||||
|
||||
data->newsType = WONDER_NEWS_NONE;
|
||||
itemId = data->berry + FIRST_BERRY_INDEX - 1;
|
||||
data->berry = 0;
|
||||
IncrementRewardCounter(data);
|
||||
return itemId;
|
||||
}
|
||||
|
||||
static void ResetSentRewardCounter(struct WonderNewsMetadata *data)
|
||||
{
|
||||
data->sentRewardCounter = 0;
|
||||
}
|
||||
|
||||
// Track number of times a reward was received (or attmepted to receive) for sending Wonder News to a link partner.
|
||||
static void IncrementSentRewardCounter(struct WonderNewsMetadata *data)
|
||||
{
|
||||
data->sentRewardCounter++;
|
||||
if (data->sentRewardCounter > MAX_SENT_REWARD)
|
||||
data->sentRewardCounter = MAX_SENT_REWARD;
|
||||
}
|
||||
|
||||
static void IncrementRewardCounter(struct WonderNewsMetadata *data)
|
||||
{
|
||||
data->rewardCounter++;
|
||||
if (data->rewardCounter > MAX_REWARD)
|
||||
data->rewardCounter = MAX_REWARD;
|
||||
}
|
||||
|
||||
static u32 GetRewardType(struct WonderNewsMetadata *data)
|
||||
{
|
||||
if (data->rewardCounter == MAX_REWARD)
|
||||
return NEWS_REWARD_AT_MAX;
|
||||
|
||||
switch (data->newsType)
|
||||
{
|
||||
case WONDER_NEWS_NONE:
|
||||
return NEWS_REWARD_WAITING;
|
||||
case WONDER_NEWS_RECV_FRIEND:
|
||||
return NEWS_REWARD_RECV_SMALL;
|
||||
case WONDER_NEWS_RECV_WIRELESS:
|
||||
return NEWS_REWARD_RECV_BIG;
|
||||
case WONDER_NEWS_SENT:
|
||||
if (data->sentRewardCounter < MAX_SENT_REWARD - 1)
|
||||
return NEWS_REWARD_SENT_SMALL;
|
||||
return NEWS_REWARD_SENT_BIG;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("menews_jisan.c"), 383);
|
||||
return NEWS_REWARD_NONE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user