Merge pull request #580 from GriffinRichards/sync-rfu2

Sync wireless link
This commit is contained in:
GriffinR
2022-11-14 11:39:05 -05:00
committed by GitHub
59 changed files with 4600 additions and 4521 deletions
+1 -1
View File
@@ -519,7 +519,7 @@ void TryReceiveLinkBattleData(void)
if (gReceivedRemoteLinkPlayers != 0 && (gBattleTypeFlags & BATTLE_TYPE_LINK_IN_BATTLE) && (gLinkPlayers[0].linkType == 0x2211))
{
LinkRfu_DestroyIdleTask();
DestroyTask_RfuIdle();
for (i = 0; i < GetLinkPlayerCount(); i++)
{
if (GetBlockReceivedStatus() & gBitTable[i])
+3 -3
View File
@@ -969,9 +969,9 @@ static u32 QuitBerryCrush(MainCallback callback)
#define ERROR_EXIT(exitCallback) \
{ \
SetMainCallback2(exitCallback); \
Rfu.linkman_param[0] = 0; \
Rfu.linkman_param[1] = 0; \
Rfu.errorState = 1; \
gRfu.errorParams[0] = 0; \
gRfu.errorParams[1] = 0; \
gRfu.errorState = 1; \
}
+2 -2
View File
@@ -897,7 +897,7 @@ static void Task_StartWiredTrade(u8 taskId)
case 3:
if (!gReceivedRemoteLinkPlayers)
{
SetMainCallback2(CB2_ReturnFromLinkTrade);
SetMainCallback2(CB2_StartCreateTradeMenu);
DestroyTask(taskId);
}
break;
@@ -929,7 +929,7 @@ static void Task_StartWirelessTrade(u8 taskId)
case 3:
if (IsLinkTaskFinished())
{
UnionRoom_CreateTask_CallCB2ReturnFromLinkTrade();
CreateTask_CreateTradeMenu();
DestroyTask(taskId);
}
break;
+471
View File
@@ -0,0 +1,471 @@
static const u8 *const sLinkGroupActivityNameTexts[] = {
[ACTIVITY_NONE] = gText_UR_EmptyString,
[ACTIVITY_BATTLE_SINGLE] = gText_UR_SingleBattle,
[ACTIVITY_BATTLE_DOUBLE] = gText_UR_DoubleBattle,
[ACTIVITY_BATTLE_MULTI] = gText_UR_MultiBattle,
[ACTIVITY_TRADE] = gText_UR_PokemonTrades,
[ACTIVITY_CHAT] = gText_UR_Chat,
[ACTIVITY_WONDER_CARD_DUP] = gText_UR_WonderCards,
[ACTIVITY_WONDER_NEWS_DUP] = gText_UR_WonderNews,
[ACTIVITY_CARD] = gText_UR_Cards,
[ACTIVITY_POKEMON_JUMP] = gText_UR_PokemonJump,
[ACTIVITY_BERRY_CRUSH] = gText_UR_BerryCrush,
[ACTIVITY_BERRY_PICK] = gText_UR_BerryPicking,
[ACTIVITY_SEARCH] = gText_UR_Search,
[ACTIVITY_SPIN_TRADE] = gText_UR_SpinTrade,
[ACTIVITY_ITEM_TRADE] = gText_UR_ItemTrade,
[ACTIVITY_RECORD_CORNER] = gText_UR_EmptyString,
[ACTIVITY_BERRY_BLENDER] = gText_UR_EmptyString,
[ACTIVITY_ACCEPT] = gText_UR_EmptyString,
[ACTIVITY_DECLINE] = gText_UR_EmptyString,
[ACTIVITY_NPCTALK] = gText_UR_EmptyString,
[ACTIVITY_PLYRTALK] = gText_UR_EmptyString,
[ACTIVITY_WONDER_CARD] = gText_UR_WonderCards,
[ACTIVITY_WONDER_NEWS] = gText_UR_WonderNews
};
static const struct WindowTemplate sWindowTemplate_BButtonCancel = {
.bg = 0,
.tilemapLeft = 0,
.tilemapTop = 0,
.width = 30,
.height = 2,
.paletteNum = 0xF,
.baseBlock = 0x008
};
// Minimum and maximum number of players for a link group
// A minimum of 0 means the min and max are equal
#define LINK_GROUP_CAPACITY(min, max)(((min) << 12) | ((max) << 8))
#define GROUP_MAX(capacity)(capacity & 0x0F)
#define GROUP_MIN(capacity)(capacity >> 4)
#define GROUP_MIN2(capacity)(capacity & 0xF0) // Unnecessary to have both, but needed to match
static const u32 sLinkGroupToActivityAndCapacity[] = {
[LINK_GROUP_SINGLE_BATTLE] = ACTIVITY_BATTLE_SINGLE | LINK_GROUP_CAPACITY(0, 2),
[LINK_GROUP_DOUBLE_BATTLE] = ACTIVITY_BATTLE_DOUBLE | LINK_GROUP_CAPACITY(0, 2),
[LINK_GROUP_MULTI_BATTLE] = ACTIVITY_BATTLE_MULTI | LINK_GROUP_CAPACITY(0, 4),
[LINK_GROUP_TRADE] = ACTIVITY_TRADE | LINK_GROUP_CAPACITY(0, 2),
[LINK_GROUP_POKEMON_JUMP] = ACTIVITY_POKEMON_JUMP | LINK_GROUP_CAPACITY(2, 5),
[LINK_GROUP_BERRY_CRUSH] = ACTIVITY_BERRY_CRUSH | LINK_GROUP_CAPACITY(2, 5),
[LINK_GROUP_BERRY_PICKING] = ACTIVITY_BERRY_PICK | LINK_GROUP_CAPACITY(3, 5),
[LINK_GROUP_WONDER_CARD] = ACTIVITY_SPIN_TRADE | LINK_GROUP_CAPACITY(3, 5),
[LINK_GROUP_WONDER_NEWS] = ACTIVITY_ITEM_TRADE | LINK_GROUP_CAPACITY(3, 5)
};
static const struct WindowTemplate sWindowTemplate_List_PossibleGroupMembers = {
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 3,
.width = 13,
.height = 10,
.paletteNum = 15,
.baseBlock = 0x044
};
static const struct WindowTemplate sWindowTemplate_NumPlayerMode = {
.bg = 0,
.tilemapLeft = 16,
.tilemapTop = 3,
.width = 7,
.height = 4,
.paletteNum = 15,
.baseBlock = 0x0C6
};
const struct ListMenuItem sListMenuItems_PossibleGroupMembers[] = {
{gText_UR_EmptyString, 0},
{gText_UR_EmptyString, 1},
{gText_UR_EmptyString, 2},
{gText_UR_EmptyString, 3},
{gText_UR_EmptyString, 4}
};
static const struct ListMenuTemplate sListMenuTemplate_PossibleGroupMembers = {
.items = sListMenuItems_PossibleGroupMembers,
.moveCursorFunc = NULL,
.itemPrintFunc = ItemPrintFunc_PossibleGroupMembers,
.totalItems = ARRAY_COUNT(sListMenuItems_PossibleGroupMembers),
.maxShowed = 5,
.windowId = 0,
.header_X = 0,
.item_X = 1,
.cursor_X = 0,
.upText_Y = 0,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 0,
.itemVerticalPadding = 2,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = FONT_2,
.cursorKind = 1
};
static const struct WindowTemplate sWindowTemplate_GroupList = {
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 3,
.width = 17,
.height = 10,
.paletteNum = 15,
.baseBlock = 0x044
};
static const struct WindowTemplate sWindowTemplate_PlayerNameAndId = {
.bg = 0,
.tilemapLeft = 20,
.tilemapTop = 3,
.width = 7,
.height = 4,
.paletteNum = 15,
.baseBlock = 0x0EE
};
static const struct ListMenuItem sListMenuItems_UnionRoomGroups[] = {
{gText_UR_EmptyString, 0},
{gText_UR_EmptyString, 1},
{gText_UR_EmptyString, 2},
{gText_UR_EmptyString, 3},
{gText_UR_EmptyString, 4},
{gText_UR_EmptyString, 5},
{gText_UR_EmptyString, 6},
{gText_UR_EmptyString, 7},
{gText_UR_EmptyString, 8},
{gText_UR_EmptyString, 9},
{gText_UR_EmptyString, 10},
{gText_UR_EmptyString, 11},
{gText_UR_EmptyString, 12},
{gText_UR_EmptyString, 13},
{gText_UR_EmptyString, 14},
{gText_UR_EmptyString, 15}
};
static const struct ListMenuTemplate sListMenuTemplate_UnionRoomGroups = {
.items = sListMenuItems_UnionRoomGroups,
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
.itemPrintFunc = ListMenuItemPrintFunc_UnionRoomGroups,
.totalItems = ARRAY_COUNT(sListMenuItems_UnionRoomGroups),
.maxShowed = 5,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 0,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 0,
.itemVerticalPadding = 2,
.scrollMultiple = LIST_MULTIPLE_SCROLL_DPAD,
.fontId = FONT_2,
.cursorKind = 0
};
static const struct WindowTemplate sWindowTemplate_InviteToActivity = {
.bg = 0,
.tilemapLeft = 20,
.tilemapTop = 6,
.width = 8,
.height = 7,
.paletteNum = 15,
.baseBlock = 0x001
};
static const struct ListMenuItem sListMenuItems_InviteToActivity[] = {
{gText_UR_Greetings, ACTIVITY_CARD | LINK_GROUP_CAPACITY(0, 2)},
{gText_UR_Battle, ACTIVITY_BATTLE_SINGLE | IN_UNION_ROOM | LINK_GROUP_CAPACITY(0, 2)},
{gText_UR_Chat2, ACTIVITY_CHAT | IN_UNION_ROOM | LINK_GROUP_CAPACITY(0, 2)},
{gText_UR_Exit, ACTIVITY_NONE | IN_UNION_ROOM }
};
static const struct ListMenuTemplate sListMenuTemplate_InviteToActivity = {
.items = sListMenuItems_InviteToActivity,
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
.itemPrintFunc = NULL,
.totalItems = ARRAY_COUNT(sListMenuItems_InviteToActivity),
.maxShowed = 4,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 0,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 1,
.itemVerticalPadding = 0,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = FONT_2,
.cursorKind = 0
};
static const struct WindowTemplate sWindowTemplate_RegisterForTrade = {
.bg = 0,
.tilemapLeft = 18,
.tilemapTop = 8,
.width = 11,
.height = 5,
.paletteNum = 15,
.baseBlock = 0x001
};
static const struct ListMenuItem sListMenuItems_RegisterForTrade[] = {
{gText_Register, 1},
{gText_UR_Info, 2},
{gText_UR_Exit, 3}
};
static const struct ListMenuTemplate sListMenuTemplate_RegisterForTrade = {
.items = sListMenuItems_RegisterForTrade,
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
.itemPrintFunc = NULL,
.totalItems = ARRAY_COUNT(sListMenuItems_RegisterForTrade),
.maxShowed = 3,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 0,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 1,
.itemVerticalPadding = 0,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = FONT_2,
.cursorKind = 0
};
static const struct WindowTemplate sWindowTemplate_TypeNames = {
.bg = 0,
.tilemapLeft = 20,
.tilemapTop = 2,
.width = 9,
.height = 11,
.paletteNum = 15,
.baseBlock = 0x001
};
static const struct ListMenuItem sListMenuItems_TypeNames[NUMBER_OF_MON_TYPES] = {
{ gTypeNames[TYPE_NORMAL], TYPE_NORMAL },
{ gTypeNames[TYPE_FIRE], TYPE_FIRE },
{ gTypeNames[TYPE_WATER], TYPE_WATER },
{ gTypeNames[TYPE_ELECTRIC], TYPE_ELECTRIC },
{ gTypeNames[TYPE_GRASS], TYPE_GRASS },
{ gTypeNames[TYPE_ICE], TYPE_ICE },
{ gTypeNames[TYPE_GROUND], TYPE_GROUND },
{ gTypeNames[TYPE_ROCK], TYPE_ROCK },
{ gTypeNames[TYPE_FLYING], TYPE_FLYING },
{ gTypeNames[TYPE_PSYCHIC], TYPE_PSYCHIC },
{ gTypeNames[TYPE_FIGHTING], TYPE_FIGHTING },
{ gTypeNames[TYPE_POISON], TYPE_POISON },
{ gTypeNames[TYPE_BUG], TYPE_BUG },
{ gTypeNames[TYPE_GHOST], TYPE_GHOST },
{ gTypeNames[TYPE_DRAGON], TYPE_DRAGON },
{ gTypeNames[TYPE_STEEL], TYPE_STEEL },
{ gTypeNames[TYPE_DARK], TYPE_DARK },
{ gText_UR_Exit, NUMBER_OF_MON_TYPES }
};
static const struct ListMenuTemplate sListMenuTemplate_TypeNames = {
.items = sListMenuItems_TypeNames,
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
.itemPrintFunc = NULL,
.totalItems = NUMBER_OF_MON_TYPES,
.maxShowed = 6,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 2,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 1,
.itemVerticalPadding = 0,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = FONT_2,
.cursorKind = 0
};
static const struct WindowTemplate sWindowTemplate_TradingBoardHeader = {
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 1,
.width = 28,
.height = 2,
.paletteNum = 13,
.baseBlock = 0x001
};
static const struct WindowTemplate sWindowTemplate_TradingBoardMain = {
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 5,
.width = 28,
.height = 10,
.paletteNum = 13,
.baseBlock = 0x039
};
static const struct ListMenuItem sListMenuItems_TradeBoard[] = {
{gText_UR_EmptyString, -3},
{gText_UR_EmptyString, 0},
{gText_UR_EmptyString, 1},
{gText_UR_EmptyString, 2},
{gText_UR_EmptyString, 3},
{gText_UR_EmptyString, 4},
{gText_UR_EmptyString, 5},
{gText_UR_EmptyString, 6},
{gText_UR_EmptyString, 7},
{gText_UR_Exit2, 8}
};
static const struct ListMenuTemplate sListMenuTemplate_TradeBoard = {
.items = sListMenuItems_TradeBoard,
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
.itemPrintFunc = TradeBoardListMenuItemPrintFunc,
.totalItems = ARRAY_COUNT(sListMenuItems_TradeBoard),
.maxShowed = 5,
.windowId = 0,
.header_X = 0,
.item_X = 12,
.cursor_X = 0,
.upText_Y = 2,
.cursorPal = 14,
.fillValue = 15,
.cursorShadowPal = 13,
.lettersSpacing = 1,
.itemVerticalPadding = 1,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = FONT_2,
.cursorKind = 0
};
static const struct WindowTemplate sWindowTemplate_Unused = {
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 5,
.width = 28,
.height = 10,
.paletteNum = 13,
.baseBlock = 0x039
};
static const struct ListMenuItem sListMenuItems_Unused[] = {
{gText_UR_EmptyString, 0},
{gText_UR_EmptyString, 1},
{gText_UR_EmptyString, 2},
{gText_UR_EmptyString, 3},
{gText_UR_EmptyString, 4},
{gText_UR_EmptyString, 5},
{gText_UR_EmptyString, 6},
{gText_UR_EmptyString, 7},
{gText_UR_EmptyString, 8},
{gText_UR_EmptyString, 9},
{gText_UR_EmptyString, 10},
{gText_UR_EmptyString, 11},
{gText_UR_EmptyString, 12},
{gText_UR_EmptyString, 13},
{gText_UR_EmptyString, 14},
{gText_UR_EmptyString, 15}
};
static const struct ListMenuTemplate sListMenuTemplate_Unused = {
.items = sListMenuItems_Unused,
.moveCursorFunc = ListMenuDefaultCursorMoveFunc,
.itemPrintFunc = ItemPrintFunc_Unused,
.totalItems = ARRAY_COUNT(sListMenuItems_Unused),
.maxShowed = 4,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 1,
.upText_Y = 0,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 1,
.itemVerticalPadding = 0,
.scrollMultiple = LIST_MULTIPLE_SCROLL_DPAD,
.fontId = FONT_2,
.cursorKind = 0
};
static const struct RfuPlayerData sRfuPlayerData_Dummy = {};
ALIGNED(4) static const u8 sAcceptedActivityIds_SingleBattle[] = {ACTIVITY_BATTLE_SINGLE, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_DoubleBattle[] = {ACTIVITY_BATTLE_DOUBLE, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_MultiBattle[] = {ACTIVITY_BATTLE_MULTI, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_Trade[] = {ACTIVITY_TRADE, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_PokemonJump[] = {ACTIVITY_POKEMON_JUMP, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_BerryCrush[] = {ACTIVITY_BERRY_CRUSH, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_BerryPicking[] = {ACTIVITY_BERRY_PICK, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_WonderCard[] = {ACTIVITY_WONDER_CARD, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_WonderNews[] = {ACTIVITY_WONDER_NEWS, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_Resume[] = {
IN_UNION_ROOM | ACTIVITY_NONE,
IN_UNION_ROOM | ACTIVITY_BATTLE_SINGLE,
IN_UNION_ROOM | ACTIVITY_TRADE,
IN_UNION_ROOM | ACTIVITY_CHAT,
IN_UNION_ROOM | ACTIVITY_CARD,
IN_UNION_ROOM | ACTIVITY_ACCEPT,
IN_UNION_ROOM | ACTIVITY_DECLINE,
IN_UNION_ROOM | ACTIVITY_NPCTALK,
IN_UNION_ROOM | ACTIVITY_PLYRTALK,
0xFF
};
ALIGNED(4) static const u8 sAcceptedActivityIds_Init[] = {ACTIVITY_SEARCH, 0xFF};
ALIGNED(4) static const u8 sAcceptedActivityIds_Unk11[] = {
ACTIVITY_BATTLE_SINGLE,
ACTIVITY_BATTLE_DOUBLE,
ACTIVITY_BATTLE_MULTI,
ACTIVITY_TRADE,
ACTIVITY_POKEMON_JUMP,
ACTIVITY_BERRY_CRUSH,
ACTIVITY_BERRY_PICK,
ACTIVITY_WONDER_CARD,
ACTIVITY_WONDER_NEWS,
ACTIVITY_SPIN_TRADE,
0xFF
};
ALIGNED(4) static const u8 sAcceptedActivityIds_Unk12[] = {
ACTIVITY_BATTLE_SINGLE,
ACTIVITY_BATTLE_DOUBLE,
ACTIVITY_BATTLE_MULTI,
ACTIVITY_TRADE,
ACTIVITY_BERRY_CRUSH,
0xFF
};
static const u8 *const sAcceptedActivityIds[NUM_LINK_GROUP_TYPES] = {
[LINK_GROUP_SINGLE_BATTLE] = sAcceptedActivityIds_SingleBattle,
[LINK_GROUP_DOUBLE_BATTLE] = sAcceptedActivityIds_DoubleBattle,
[LINK_GROUP_MULTI_BATTLE] = sAcceptedActivityIds_MultiBattle,
[LINK_GROUP_TRADE] = sAcceptedActivityIds_Trade,
[LINK_GROUP_POKEMON_JUMP] = sAcceptedActivityIds_PokemonJump,
[LINK_GROUP_BERRY_CRUSH] = sAcceptedActivityIds_BerryCrush,
[LINK_GROUP_BERRY_PICKING] = sAcceptedActivityIds_BerryPicking,
[LINK_GROUP_WONDER_CARD] = sAcceptedActivityIds_WonderCard,
[LINK_GROUP_WONDER_NEWS] = sAcceptedActivityIds_WonderNews,
[LINK_GROUP_UNION_ROOM_RESUME] = sAcceptedActivityIds_Resume,
[LINK_GROUP_UNION_ROOM_INIT] = sAcceptedActivityIds_Init,
[LINK_GROUP_UNK_11] = sAcceptedActivityIds_Unk11,
[LINK_GROUP_UNK_12] = sAcceptedActivityIds_Unk12,
};
static const u8 sLinkGroupToURoomActivity[] = {
[LINK_GROUP_SINGLE_BATTLE] = ACTIVITY_BATTLE_SINGLE,
[LINK_GROUP_DOUBLE_BATTLE] = ACTIVITY_BATTLE_DOUBLE,
[LINK_GROUP_MULTI_BATTLE] = ACTIVITY_BATTLE_MULTI,
[LINK_GROUP_TRADE] = ACTIVITY_TRADE,
[LINK_GROUP_POKEMON_JUMP] = ACTIVITY_POKEMON_JUMP,
[LINK_GROUP_BERRY_CRUSH] = ACTIVITY_BERRY_CRUSH,
[LINK_GROUP_BERRY_PICKING] = ACTIVITY_BERRY_PICK,
[LINK_GROUP_WONDER_CARD] = ACTIVITY_WONDER_CARD,
[LINK_GROUP_WONDER_NEWS] = ACTIVITY_WONDER_NEWS
};
// Unused
static const u8 sDotSeparatedValues[] = _("{DYNAMIC 00}·{DYNAMIC 01}");
+5 -5
View File
@@ -222,7 +222,7 @@ bool8 IsWirelessAdapterConnected(void)
SetWirelessCommType1();
InitRFUAPI();
sub_80FB128(TRUE);
RfuSetIgnoreError(TRUE);
if (rfu_LMAN_REQBN_softReset_and_checkID() == RFU_ID)
{
rfu_REQ_stopMode();
@@ -718,7 +718,7 @@ void ClearLinkCallback_2(void)
u8 GetLinkPlayerCount(void)
{
if (gWirelessCommType)
return GetRfuPlayerCount();
return Rfu_GetLinkPlayerCount();
return EXTRACT_PLAYER_COUNT(gLinkStatus);
}
@@ -924,7 +924,7 @@ static void SendBerryBlenderNoSpaceForPokeblocks(void)
u8 GetMultiplayerId(void)
{
if (gWirelessCommType == 1)
return LinkRfu_GetMultiplayerId();
return Rfu_GetMultiplayerId();
return SIO_MULTI_CNT->id;
}
@@ -1576,8 +1576,8 @@ bool8 HandleLinkConnection(void)
}
else
{
main1Failed = LinkRfuMain1(); // Always returns FALSE
main2Failed = LinkRfuMain2();
main1Failed = RfuMain1(); // Always returns FALSE
main2Failed = RfuMain2();
if (IsSendingKeysOverCable() == TRUE)
{
// This will never be reached.
+1149 -1061
View File
File diff suppressed because it is too large Load Diff
+162 -217
View File
@@ -6,12 +6,35 @@
#include "link_rfu.h"
#include "random.h"
static EWRAM_DATA u8 gWirelessStatusIndicatorSpriteId = 0;
enum {
WIRELESS_STATUS_ANIM_3_BARS,
WIRELESS_STATUS_ANIM_2_BARS,
WIRELESS_STATUS_ANIM_1_BAR,
WIRELESS_STATUS_ANIM_SEARCHING,
WIRELESS_STATUS_ANIM_ERROR,
};
static const u16 gWirelessLinkIconPalette[] = INCBIN_U16("graphics/interface/wireless_link_icon.gbapal");
#define TAG_GFX_STATUS_INDICATOR 0xD431
#define TAG_PAL_STATUS_INDICATOR 0xD432
static const u32 gWirelessLinkIconPic[] = INCBIN_U32("graphics/interface/wireless_link_icon.4bpp.lz");
#define UNUSED_QUEUE_NUM_SLOTS 2
#define UNUSED_QUEUE_SLOT_LENGTH 256
struct RfuUnusedQueue
{
u8 slots[UNUSED_QUEUE_NUM_SLOTS][UNUSED_QUEUE_SLOT_LENGTH];
vu8 recvSlot;
vu8 sendSlot;
vu8 count;
vu8 full;
};
static EWRAM_DATA u8 sWirelessStatusIndicatorSpriteId = 0;
static const u16 sWirelessLinkIconPalette[] = INCBIN_U16("graphics/link/wireless_icon.gbapal");
static const u32 sWirelessLinkIconPic[] = INCBIN_U32("graphics/link/wireless_icon.4bpp.lz");
// Most of the below two tables won't make sense with ASCII encoding.
static const u8 sWireless_ASCIItoRSETable[] = {
EOS,
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x37,
@@ -222,8 +245,7 @@ static const struct OamData sWirelessStatusIndicatorOamData =
.paletteNum = 0,
};
static const union AnimCmd sWirelessStatusIndicatorAnim0[] = {
// 3 bars
static const union AnimCmd sWirelessStatusIndicator_3Bars[] = {
ANIMCMD_FRAME( 4, 5),
ANIMCMD_FRAME( 8, 5),
ANIMCMD_FRAME(12, 5),
@@ -233,8 +255,7 @@ static const union AnimCmd sWirelessStatusIndicatorAnim0[] = {
ANIMCMD_JUMP(0)
};
static const union AnimCmd sWirelessStatusIndicatorAnim1[] = {
// 2 bars
static const union AnimCmd sWirelessStatusIndicator_2Bars[] = {
ANIMCMD_FRAME( 4, 5),
ANIMCMD_FRAME( 8, 5),
ANIMCMD_FRAME(12, 10),
@@ -242,46 +263,43 @@ static const union AnimCmd sWirelessStatusIndicatorAnim1[] = {
ANIMCMD_JUMP(0)
};
static const union AnimCmd sWirelessStatusIndicatorAnim2[] = {
// 1 bar
static const union AnimCmd sWirelessStatusIndicator_1Bar[] = {
ANIMCMD_FRAME(4, 5),
ANIMCMD_FRAME(8, 5),
ANIMCMD_JUMP(0)
};
static const union AnimCmd sWirelessStatusIndicatorAnim3[] = {
// searching
static const union AnimCmd sWirelessStatusIndicator_Searching[] = {
ANIMCMD_FRAME( 4, 10),
ANIMCMD_FRAME(20, 10),
ANIMCMD_JUMP(0)
};
static const union AnimCmd sWirelessStatusIndicatorAnim4[] = {
// error
static const union AnimCmd sWirelessStatusIndicator_Error[] = {
ANIMCMD_FRAME(24, 10),
ANIMCMD_FRAME( 4, 10),
ANIMCMD_JUMP(0)
};
static const union AnimCmd *const sWirelessStatusIndicatorAnims[] = {
sWirelessStatusIndicatorAnim0,
sWirelessStatusIndicatorAnim1,
sWirelessStatusIndicatorAnim2,
sWirelessStatusIndicatorAnim3,
sWirelessStatusIndicatorAnim4
[WIRELESS_STATUS_ANIM_3_BARS] = sWirelessStatusIndicator_3Bars,
[WIRELESS_STATUS_ANIM_2_BARS] = sWirelessStatusIndicator_2Bars,
[WIRELESS_STATUS_ANIM_1_BAR] = sWirelessStatusIndicator_1Bar,
[WIRELESS_STATUS_ANIM_SEARCHING] = sWirelessStatusIndicator_Searching,
[WIRELESS_STATUS_ANIM_ERROR] = sWirelessStatusIndicator_Error
};
static const struct CompressedSpriteSheet sWirelessStatusIndicatorSpriteSheet = {
gWirelessLinkIconPic, 0x0380, 0xD431
sWirelessLinkIconPic, 0x0380, TAG_GFX_STATUS_INDICATOR
};
static const struct SpritePalette sWirelessStatusIndicatorSpritePalette = {
gWirelessLinkIconPalette, 0xD432
sWirelessLinkIconPalette, TAG_PAL_STATUS_INDICATOR
};
static const struct SpriteTemplate sWirelessStatusIndicatorSpriteTemplate = {
.tileTag = 0xD431,
.paletteTag = 0xD432,
.tileTag = TAG_GFX_STATUS_INDICATOR,
.paletteTag = TAG_PAL_STATUS_INDICATOR,
.oam = &sWirelessStatusIndicatorOamData,
.anims = sWirelessStatusIndicatorAnims,
.images = NULL,
@@ -298,13 +316,11 @@ void RfuRecvQueue_Reset(struct RfuRecvQueue *queue)
for (i = 0; i < RECV_QUEUE_NUM_SLOTS; i++)
{
for (j = 0; j < RECV_QUEUE_SLOT_LENGTH; j++)
{
for (j = 0; j < COMM_SLOT_LENGTH * MAX_RFU_PLAYERS; j++)
queue->slots[i][j] = 0;
}
}
queue->send_slot = 0;
queue->recv_slot = 0;
queue->sendSlot = 0;
queue->recvSlot = 0;
queue->count = 0;
queue->full = FALSE;
}
@@ -316,13 +332,11 @@ void RfuSendQueue_Reset(struct RfuSendQueue *queue)
for (i = 0; i < SEND_QUEUE_NUM_SLOTS; i++)
{
for (j = 0; j < SEND_QUEUE_SLOT_LENGTH; j++)
{
for (j = 0; j < COMM_SLOT_LENGTH; j++)
queue->slots[i][j] = 0;
}
}
queue->send_slot = 0;
queue->recv_slot = 0;
queue->sendSlot = 0;
queue->recvSlot = 0;
queue->count = 0;
queue->full = FALSE;
}
@@ -335,12 +349,10 @@ static void RfuUnusedQueue_Reset(struct RfuUnusedQueue *queue)
for (i = 0; i < UNUSED_QUEUE_NUM_SLOTS; i++)
{
for (j = 0; j < UNUSED_QUEUE_SLOT_LENGTH; j++)
{
queue->slots[i][j] = 0;
}
}
queue->send_slot = 0;
queue->recv_slot = 0;
queue->sendSlot = 0;
queue->recvSlot = 0;
queue->count = 0;
queue->full = FALSE;
}
@@ -356,26 +368,20 @@ void RfuRecvQueue_Enqueue(struct RfuRecvQueue *queue, u8 *src)
imeBak = REG_IME;
REG_IME = 0;
count = 0;
for (i = 0; i < RECV_QUEUE_SLOT_LENGTH; i += RECV_QUEUE_SLOT_LENGTH / MAX_RFU_PLAYERS)
for (i = 0; i < COMM_SLOT_LENGTH * MAX_RFU_PLAYERS; i += COMM_SLOT_LENGTH)
{
if (src[i] == 0 && src[i + 1] == 0)
{
count++;
}
}
if (count != MAX_RFU_PLAYERS)
{
for (i = 0; i < RECV_QUEUE_SLOT_LENGTH; i++)
{
queue->slots[queue->recv_slot][i] = src[i];
}
queue->recv_slot++;
queue->recv_slot %= RECV_QUEUE_NUM_SLOTS;
for (i = 0; i < COMM_SLOT_LENGTH * MAX_RFU_PLAYERS; i++)
queue->slots[queue->recvSlot][i] = src[i];
queue->recvSlot++;
queue->recvSlot %= RECV_QUEUE_NUM_SLOTS;
queue->count++;
for (i = 0; i < RECV_QUEUE_SLOT_LENGTH; i++)
{
for (i = 0; i < COMM_SLOT_LENGTH * MAX_RFU_PLAYERS; i++)
src[i] = 0;
}
}
REG_IME = imeBak;
}
@@ -394,26 +400,20 @@ void RfuSendQueue_Enqueue(struct RfuSendQueue *queue, u8 *src)
{
imeBak = REG_IME;
REG_IME = 0;
for (i = 0; i < SEND_QUEUE_SLOT_LENGTH; i++)
for (i = 0; i < COMM_SLOT_LENGTH; i++)
{
if (src[i] != 0)
{
break;
}
}
if (i != SEND_QUEUE_SLOT_LENGTH)
if (i != COMM_SLOT_LENGTH)
{
for (i = 0; i < SEND_QUEUE_SLOT_LENGTH; i++)
{
queue->slots[queue->recv_slot][i] = src[i];
}
queue->recv_slot++;
queue->recv_slot %= SEND_QUEUE_NUM_SLOTS;
for (i = 0; i < COMM_SLOT_LENGTH; i++)
queue->slots[queue->recvSlot][i] = src[i];
queue->recvSlot++;
queue->recvSlot %= SEND_QUEUE_NUM_SLOTS;
queue->count++;
for (i = 0; i < SEND_QUEUE_SLOT_LENGTH; i++)
{
for (i = 0; i < COMM_SLOT_LENGTH; i++)
src[i] = 0;
}
}
REG_IME = imeBak;
}
@@ -430,21 +430,17 @@ bool8 RfuRecvQueue_Dequeue(struct RfuRecvQueue *queue, u8 *dest)
imeBak = REG_IME;
REG_IME = 0;
if (queue->recv_slot == queue->send_slot || queue->full)
if (queue->recvSlot == queue->sendSlot || queue->full)
{
for (i = 0; i < RECV_QUEUE_SLOT_LENGTH; i++)
{
for (i = 0; i < COMM_SLOT_LENGTH * MAX_RFU_PLAYERS; i++)
dest[i] = 0;
}
REG_IME = imeBak;
return FALSE;
}
for (i = 0; i < RECV_QUEUE_SLOT_LENGTH; i++)
{
dest[i] = queue->slots[queue->send_slot][i];
}
queue->send_slot++;
queue->send_slot %= RECV_QUEUE_NUM_SLOTS;
for (i = 0; i < COMM_SLOT_LENGTH * MAX_RFU_PLAYERS; i++)
dest[i] = queue->slots[queue->sendSlot][i];
queue->sendSlot++;
queue->sendSlot %= RECV_QUEUE_NUM_SLOTS;
queue->count--;
REG_IME = imeBak;
return TRUE;
@@ -455,18 +451,14 @@ bool8 RfuSendQueue_Dequeue(struct RfuSendQueue *queue, u8 *dest)
s32 i;
u16 imeBak;
if (queue->recv_slot == queue->send_slot || queue->full)
{
if (queue->recvSlot == queue->sendSlot || queue->full)
return FALSE;
}
imeBak = REG_IME;
REG_IME = 0;
for (i = 0; i < SEND_QUEUE_SLOT_LENGTH; i++)
{
dest[i] = queue->slots[queue->send_slot][i];
}
queue->send_slot++;
queue->send_slot %= SEND_QUEUE_NUM_SLOTS;
for (i = 0; i < COMM_SLOT_LENGTH; i++)
dest[i] = queue->slots[queue->sendSlot][i];
queue->sendSlot++;
queue->sendSlot %= SEND_QUEUE_NUM_SLOTS;
queue->count--;
REG_IME = imeBak;
return TRUE;
@@ -482,20 +474,14 @@ void RfuBackupQueue_Enqueue(struct RfuBackupQueue *queue, const u8 *dest)
}
else
{
for (i = 0; i < BACKUP_QUEUE_SLOT_LENGTH; i++)
{
queue->slots[queue->recv_slot][i] = dest[i];
}
queue->recv_slot++;
queue->recv_slot %= BACKUP_QUEUE_NUM_SLOTS;
for (i = 0; i < COMM_SLOT_LENGTH; i++)
queue->slots[queue->recvSlot][i] = dest[i];
queue->recvSlot++;
queue->recvSlot %= BACKUP_QUEUE_NUM_SLOTS;
if (queue->count < BACKUP_QUEUE_NUM_SLOTS)
{
queue->count++;
}
else
{
queue->send_slot = queue->recv_slot;
}
queue->sendSlot = queue->recvSlot;
}
}
@@ -504,18 +490,15 @@ bool8 RfuBackupQueue_Dequeue(struct RfuBackupQueue *queue, u8 *dest)
s32 i;
if (queue->count == 0)
{
return FALSE;
}
if (dest != NULL)
{
for (i = 0; i < BACKUP_QUEUE_SLOT_LENGTH; i++)
{
dest[i] = queue->slots[queue->send_slot][i];
}
for (i = 0; i < COMM_SLOT_LENGTH; i++)
dest[i] = queue->slots[queue->sendSlot][i];
}
queue->send_slot++;
queue->send_slot %= BACKUP_QUEUE_NUM_SLOTS;
queue->sendSlot++;
queue->sendSlot %= BACKUP_QUEUE_NUM_SLOTS;
queue->count--;
return TRUE;
}
@@ -527,11 +510,9 @@ static void RfuUnusedQueue_Dequeue(struct RfuUnusedQueue *queue, u8 *dest)
if (queue->count < UNUSED_QUEUE_NUM_SLOTS)
{
for (i = 0; i < UNUSED_QUEUE_SLOT_LENGTH; i++)
{
queue->slots[queue->recv_slot][i] = dest[i];
}
queue->recv_slot++;
queue->recv_slot %= UNUSED_QUEUE_NUM_SLOTS;
queue->slots[queue->recvSlot][i] = dest[i];
queue->recvSlot++;
queue->recvSlot %= UNUSED_QUEUE_NUM_SLOTS;
queue->count++;
}
else
@@ -544,16 +525,14 @@ static bool8 RfuUnusedQueue_Enqueue(struct RfuUnusedQueue *queue, u8 *dest)
{
s32 i;
if (queue->recv_slot == queue->send_slot || queue->full)
{
if (queue->recvSlot == queue->sendSlot || queue->full)
return FALSE;
}
for (i = 0; i < UNUSED_QUEUE_SLOT_LENGTH; i++)
{
dest[i] = queue->slots[queue->send_slot][i];
}
queue->send_slot++;
queue->send_slot %= UNUSED_QUEUE_NUM_SLOTS;
dest[i] = queue->slots[queue->sendSlot][i];
queue->sendSlot++;
queue->sendSlot %= UNUSED_QUEUE_NUM_SLOTS;
queue->count--;
return TRUE;
}
@@ -621,9 +600,7 @@ static void PkmnStrToASCII(u8 *dest, const u8 *src)
s32 i;
for (i = 0; src[i] != EOS; i++)
{
dest[i] = sWireless_RSEtoASCIITable[src[i]];
}
dest[i] = 0;
}
@@ -632,9 +609,7 @@ static void ASCIIToPkmnStr(u8 *dest, const u8 *src)
s32 i;
for (i = 0; src[i] != 0; i++)
{
dest[i] = sWireless_ASCIItoRSETable[src[i]];
}
dest[i] = EOS;
}
@@ -672,40 +647,39 @@ static u8 GetConnectedChildStrength(u8 maxFlags)
return 0;
}
void InitHostRFUtgtGname(struct GFtgtGname *data, u8 activity, bool32 started, s32 child_sprite_genders)
void InitHostRfuGameData(struct RfuGameData *data, u8 activity, bool32 startedActivity, s32 partnerInfo)
{
s32 i;
for (i = 0; i < 2; i++)
{
data->unk_00.playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
}
for (i = 0; i < (s32)ARRAY_COUNT(data->compatibility.playerTrainerId); i++)
data->compatibility.playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
for (i = 0; i < RFU_CHILD_MAX; i++)
{
data->child_sprite_gender[i] = child_sprite_genders;
child_sprite_genders >>= 8;
data->partnerInfo[i] = partnerInfo;
partnerInfo >>= 8; // Each element is 1 byte
}
data->playerGender = gSaveBlock2Ptr->playerGender;
data->activity = activity;
data->started = started;
data->unk_00.language = GAME_LANGUAGE;
data->unk_00.version = GAME_VERSION;
data->unk_00.hasNews = FALSE;
data->unk_00.hasCard = FALSE;
data->unk_00.unknown = FALSE;
data->unk_00.isChampion = FlagGet(FLAG_SYS_CAN_LINK_WITH_RS);
data->unk_00.hasNationalDex = IsNationalPokedexEnabled();
data->unk_00.gameClear = FlagGet(FLAG_SYS_GAME_CLEAR);
data->startedActivity = startedActivity;
data->compatibility.language = GAME_LANGUAGE;
data->compatibility.version = GAME_VERSION;
data->compatibility.hasNews = FALSE;
data->compatibility.hasCard = FALSE;
data->compatibility.unknown = FALSE;
data->compatibility.isChampion = FlagGet(FLAG_SYS_CAN_LINK_WITH_RS);
data->compatibility.hasNationalDex = IsNationalPokedexEnabled();
data->compatibility.gameClear = FlagGet(FLAG_SYS_GAME_CLEAR);
}
/*
* ==========================================================
* ================================================================
* Returns 1 if parent, 0 if child or neutral.
* If partner serial number is valid, copies gname and uname.
* If partner serial number is valid, copies gameData and username.
* Otherwise, blanks these.
* ==========================================================
* ================================================================
*/
bool8 LinkRfu_GetNameIfCompatible(struct GFtgtGname *gname, u8 *uname, u8 idx)
bool8 Rfu_GetCompatiblePlayerData(struct RfuGameData *gameData, u8 *username, u8 idx)
{
bool8 retVal;
@@ -714,13 +688,13 @@ bool8 LinkRfu_GetNameIfCompatible(struct GFtgtGname *gname, u8 *uname, u8 idx)
retVal = TRUE;
if (IsRfuSerialNumberValid(gRfuLinkStatus->partner[idx].serialNo) && ((gRfuLinkStatus->getNameFlag >> idx) & 1))
{
memcpy(gname, &gRfuLinkStatus->partner[idx].gname, RFU_GAME_NAME_LENGTH);
memcpy(uname, gRfuLinkStatus->partner[idx].uname, RFU_USER_NAME_LENGTH);
memcpy(gameData, gRfuLinkStatus->partner[idx].gname, RFU_GAME_NAME_LENGTH);
memcpy(username, gRfuLinkStatus->partner[idx].uname, RFU_USER_NAME_LENGTH);
}
else
{
memset(gname, 0, RFU_GAME_NAME_LENGTH);
memset(uname, 0, RFU_USER_NAME_LENGTH);
memset(gameData, 0, RFU_GAME_NAME_LENGTH);
memset(username, 0, RFU_USER_NAME_LENGTH);
}
}
else
@@ -728,45 +702,39 @@ bool8 LinkRfu_GetNameIfCompatible(struct GFtgtGname *gname, u8 *uname, u8 idx)
retVal = FALSE;
if (IsRfuSerialNumberValid(gRfuLinkStatus->partner[idx].serialNo))
{
memcpy(gname, &gRfuLinkStatus->partner[idx].gname, RFU_GAME_NAME_LENGTH);
memcpy(uname, gRfuLinkStatus->partner[idx].uname, RFU_USER_NAME_LENGTH);
memcpy(gameData, gRfuLinkStatus->partner[idx].gname, RFU_GAME_NAME_LENGTH);
memcpy(username, gRfuLinkStatus->partner[idx].uname, RFU_USER_NAME_LENGTH);
}
else
{
memset(gname, 0, RFU_GAME_NAME_LENGTH);
memset(uname, 0, RFU_USER_NAME_LENGTH);
memset(gameData, 0, RFU_GAME_NAME_LENGTH);
memset(username, 0, RFU_USER_NAME_LENGTH);
}
}
return retVal;
}
/*
* ==========================================================
* Specific check for serial number 0x7F7D,
* which comes from ???
* ==========================================================
*/
bool8 LinkRfu_GetNameIfSerial7F7D(struct GFtgtGname *gname, u8 *uname, u8 idx)
bool8 Rfu_GetWonderDistributorPlayerData(struct RfuGameData *gameData, u8 *username, u8 idx)
{
bool8 retVal = FALSE;
if (gRfuLinkStatus->partner[idx].serialNo == RFU_SERIAL_7F7D)
if (gRfuLinkStatus->partner[idx].serialNo == RFU_SERIAL_WONDER_DISTRIBUTOR)
{
memcpy(gname, gRfuLinkStatus->partner[idx].gname, RFU_GAME_NAME_LENGTH);
memcpy(uname, gRfuLinkStatus->partner[idx].uname, RFU_USER_NAME_LENGTH);
memcpy(gameData, gRfuLinkStatus->partner[idx].gname, RFU_GAME_NAME_LENGTH);
memcpy(username, gRfuLinkStatus->partner[idx].uname, RFU_USER_NAME_LENGTH);
retVal = TRUE;
}
else
{
memset(gname, 0, RFU_GAME_NAME_LENGTH);
memset(uname, 0, RFU_USER_NAME_LENGTH);
memset(gameData, 0, RFU_GAME_NAME_LENGTH);
memset(username, 0, RFU_USER_NAME_LENGTH);
}
return retVal;
}
void LinkRfu3_SetGnameUnameFromStaticBuffers(struct GFtgtGname *gname, u8 *uname)
void CopyHostRfuGameDataAndUsername(struct RfuGameData *gameData, u8 *username)
{
memcpy(gname, &gHostRFUtgtGnameBuffer, RFU_GAME_NAME_LENGTH);
memcpy(uname, gHostRFUtgtUnameBuffer, RFU_USER_NAME_LENGTH);
memcpy(gameData, &gHostRfuGameData, RFU_GAME_NAME_LENGTH);
memcpy(username, gHostRfuUsername, RFU_USER_NAME_LENGTH);
}
#define sNextAnimNum data[0]
@@ -793,23 +761,23 @@ void CreateWirelessStatusIndicatorSprite(u8 x, u8 y)
gSprites[sprId].sValidator = STATUS_INDICATOR_ACTIVE;
gSprites[sprId].sTileStart = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag);
gSprites[sprId].invisible = TRUE;
gWirelessStatusIndicatorSpriteId = sprId;
sWirelessStatusIndicatorSpriteId = sprId;
}
else
{
gWirelessStatusIndicatorSpriteId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0);
gSprites[gWirelessStatusIndicatorSpriteId].sValidator = STATUS_INDICATOR_ACTIVE;
gSprites[gWirelessStatusIndicatorSpriteId].sTileStart = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag);
gSprites[gWirelessStatusIndicatorSpriteId].invisible = TRUE;
sWirelessStatusIndicatorSpriteId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0);
gSprites[sWirelessStatusIndicatorSpriteId].sValidator = STATUS_INDICATOR_ACTIVE;
gSprites[sWirelessStatusIndicatorSpriteId].sTileStart = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag);
gSprites[sWirelessStatusIndicatorSpriteId].invisible = TRUE;
}
}
void DestroyWirelessStatusIndicatorSprite(void)
{
if (gSprites[gWirelessStatusIndicatorSpriteId].sValidator == STATUS_INDICATOR_ACTIVE)
if (gSprites[sWirelessStatusIndicatorSpriteId].sValidator == STATUS_INDICATOR_ACTIVE)
{
gSprites[gWirelessStatusIndicatorSpriteId].sValidator = 0;
DestroySprite(&gSprites[gWirelessStatusIndicatorSpriteId]);
gSprites[sWirelessStatusIndicatorSpriteId].sValidator = 0;
DestroySprite(&gSprites[sWirelessStatusIndicatorSpriteId]);
gMain.oamBuffer[125] = gDummyOamData;
CpuCopy16(&gDummyOamData, (struct OamData *)OAM + 125, sizeof(struct OamData));
}
@@ -818,11 +786,9 @@ void DestroyWirelessStatusIndicatorSprite(void)
void LoadWirelessStatusIndicatorSpriteGfx(void)
{
if (GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag) == 0xFFFF)
{
LoadCompressedSpriteSheet(&sWirelessStatusIndicatorSpriteSheet);
}
LoadSpritePalette(&sWirelessStatusIndicatorSpritePalette);
gWirelessStatusIndicatorSpriteId = 0xFF;
sWirelessStatusIndicatorSpriteId = SPRITE_NONE;
}
static u8 GetParentSignalStrength(void)
@@ -832,19 +798,17 @@ static u8 GetParentSignalStrength(void)
for (i = 0; i < RFU_CHILD_MAX; i++)
{
if (flags & 1)
{
return gRfuLinkStatus->strength[i];
}
flags >>= 1;
}
return 0;
}
static void SetAndRestartWirelessStatusIndicatorAnim(struct Sprite *sprite, s32 signalStrengthAnimNum)
static void SetAndRestartWirelessStatusIndicatorAnim(struct Sprite *sprite, s32 animNum)
{
if (sprite->sCurrAnimNum != signalStrengthAnimNum)
if (sprite->sCurrAnimNum != animNum)
{
sprite->sCurrAnimNum = signalStrengthAnimNum;
sprite->sCurrAnimNum = animNum;
sprite->sFrameDelay = 0;
sprite->sFrameIdx = 0;
}
@@ -852,45 +816,38 @@ static void SetAndRestartWirelessStatusIndicatorAnim(struct Sprite *sprite, s32
void UpdateWirelessStatusIndicatorSprite(void)
{
if (gWirelessStatusIndicatorSpriteId != 0xFF && gSprites[gWirelessStatusIndicatorSpriteId].sValidator == STATUS_INDICATOR_ACTIVE)
if (sWirelessStatusIndicatorSpriteId != SPRITE_NONE && gSprites[sWirelessStatusIndicatorSpriteId].sValidator == STATUS_INDICATOR_ACTIVE)
{
struct Sprite *sprite = &gSprites[gWirelessStatusIndicatorSpriteId];
struct Sprite *sprite = &gSprites[sWirelessStatusIndicatorSpriteId];
u8 signalStrength = RFU_LINK_ICON_LEVEL4_MAX;
u8 i = 0;
// Get weakest signal strength
if (gRfuLinkStatus->parentChild == MODE_PARENT)
{
for (i = 0; i < GetLinkPlayerCount() - 1; i++)
{
if (signalStrength >= GetConnectedChildStrength(i + 1))
{
signalStrength = GetConnectedChildStrength(i + 1);
}
}
}
else
{
signalStrength = GetParentSignalStrength();
}
// Set signal strength sprite anim number
if (IsRfuRecoveringFromLinkLoss() == TRUE)
{
sprite->sNextAnimNum = 4;
}
sprite->sNextAnimNum = WIRELESS_STATUS_ANIM_ERROR;
else if (signalStrength <= RFU_LINK_ICON_LEVEL1_MAX)
{
sprite->sNextAnimNum = 3;
}
sprite->sNextAnimNum = WIRELESS_STATUS_ANIM_SEARCHING;
else if (signalStrength >= RFU_LINK_ICON_LEVEL2_MIN && signalStrength <= RFU_LINK_ICON_LEVEL2_MAX)
{
sprite->sNextAnimNum = 2;
}
sprite->sNextAnimNum = WIRELESS_STATUS_ANIM_1_BAR;
else if (signalStrength >= RFU_LINK_ICON_LEVEL3_MIN && signalStrength <= RFU_LINK_ICON_LEVEL3_MAX)
{
sprite->sNextAnimNum = 1;
}
sprite->sNextAnimNum = WIRELESS_STATUS_ANIM_2_BARS;
else if (signalStrength >= RFU_LINK_ICON_LEVEL4_MIN)
{
sprite->sNextAnimNum = 0;
}
sprite->sNextAnimNum = WIRELESS_STATUS_ANIM_3_BARS;
if (sprite->sNextAnimNum != sprite->sSavedAnimNum)
{
SetAndRestartWirelessStatusIndicatorAnim(sprite, sprite->sNextAnimNum);
@@ -901,9 +858,7 @@ void UpdateWirelessStatusIndicatorSprite(void)
sprite->sFrameIdx++;
sprite->sFrameDelay = 0;
if (sprite->anims[sprite->sCurrAnimNum][sprite->sFrameIdx].type == -2) // ANIMCMD_JUMP
{
sprite->sFrameIdx = 0;
}
}
else
{
@@ -934,7 +889,7 @@ static void CopyTrainerRecord(struct TrainerNameRecord *dest, u32 trainerId, con
{
int i;
dest->trainerId = trainerId;
for (i = 0; i < 7; i++)
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
{
if (name[i] == EOS)
break;
@@ -948,9 +903,7 @@ static void ZeroName(u8 *name)
s32 i;
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
{
*name++ = 0;
}
}
static bool32 NameIsEmpty(const u8 *name)
@@ -960,15 +913,13 @@ static bool32 NameIsEmpty(const u8 *name)
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
{
if (*name++ != 0)
{
return FALSE;
}
}
return TRUE;
}
// Save the currently connected players into the trainer records, shifting all previous records down.
void RecordMixTrainerNames(void)
void SaveLinkTrainerNames(void)
{
if (gWirelessCommType != 0)
{
@@ -976,13 +927,13 @@ void RecordMixTrainerNames(void)
s32 j;
s32 nextSpace;
s32 connectedTrainerRecordIndices[5];
struct TrainerNameRecord *newRecords = AllocZeroed(20 * sizeof(struct TrainerNameRecord));
struct TrainerNameRecord *newRecords = AllocZeroed(sizeof(gSaveBlock1Ptr->trainerNameRecords));
// Check if we already have a record saved for connected trainers.
for (i = 0; i < GetLinkPlayerCount(); i++)
{
connectedTrainerRecordIndices[i] = -1;
for (j = 0; j < 20; j++)
for (j = 0; j < (int)ARRAY_COUNT(gSaveBlock1Ptr->trainerNameRecords); j++)
{
if ((u16)gLinkPlayers[i].trainerId == gSaveBlock1Ptr->trainerNameRecords[j].trainerId && StringCompare(gLinkPlayers[i].name, gSaveBlock1Ptr->trainerNameRecords[j].trainerName) == 0)
{
@@ -1001,29 +952,25 @@ void RecordMixTrainerNames(void)
// If we already had a record for this trainer, wipe it so that the next step doesn't duplicate it.
if (connectedTrainerRecordIndices[i] >= 0)
{
ZeroName(gSaveBlock1Ptr->trainerNameRecords[connectedTrainerRecordIndices[i]].trainerName);
}
nextSpace++;
}
}
// Copy all non-empty records to the new list, in the order they appear on the old list. If the list is full,
// the last (oldest) records will be dropped.
for (i = 0; i < 20; i++)
for (i = 0; i < (int)ARRAY_COUNT(gSaveBlock1Ptr->trainerNameRecords); i++)
{
if (!NameIsEmpty(gSaveBlock1Ptr->trainerNameRecords[i].trainerName))
{
CopyTrainerRecord(&newRecords[nextSpace], gSaveBlock1Ptr->trainerNameRecords[i].trainerId, gSaveBlock1Ptr->trainerNameRecords[i].trainerName);
if (++nextSpace >= 20)
{
if (++nextSpace >= (int)ARRAY_COUNT(gSaveBlock1Ptr->trainerNameRecords))
break;
}
}
}
// Finalize the new list, and clean up.
memcpy(gSaveBlock1Ptr->trainerNameRecords, newRecords, 20 * sizeof(struct TrainerNameRecord));
memcpy(gSaveBlock1Ptr->trainerNameRecords, newRecords, sizeof(gSaveBlock1Ptr->trainerNameRecords));
Free(newRecords);
}
}
@@ -1032,16 +979,14 @@ bool32 PlayerHasMetTrainerBefore(u16 id, u8 *name)
{
s32 i;
for (i = 0; i < 20; i++)
for (i = 0; i < (int)ARRAY_COUNT(gSaveBlock1Ptr->trainerNameRecords); i++)
{
if (StringCompareN(gSaveBlock1Ptr->trainerNameRecords[i].trainerName, name, 7) == 0 && gSaveBlock1Ptr->trainerNameRecords[i].trainerId == id)
{
if (StringCompareN(gSaveBlock1Ptr->trainerNameRecords[i].trainerName, name, PLAYER_NAME_LENGTH) == 0
&& gSaveBlock1Ptr->trainerNameRecords[i].trainerId == id)
return TRUE;
}
if (NameIsEmpty(gSaveBlock1Ptr->trainerNameRecords[i].trainerName))
{
return FALSE;
}
}
return FALSE;
}
+1 -1
View File
@@ -358,7 +358,7 @@ extern void ProcessDma3Requests(void);
static void VBlankIntr(void)
{
if (gWirelessCommType)
RFUVSync();
RfuVSync();
else if (!gLinkVSyncDisabled)
LinkVSync();
+9 -9
View File
@@ -263,7 +263,7 @@ static void Task_EReaderComm(u8 taskId)
switch (data->state)
{
case 0:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_ReceiveMysteryGiftWithEReader))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_ReceiveMysteryGiftWithEReader))
data->state = 1;
break;
case 1:
@@ -285,7 +285,7 @@ static void Task_EReaderComm(u8 taskId)
data->state = 13;
break;
case 4:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_SelectConnectFromEReaderMenu))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_SelectConnectFromEReaderMenu))
{
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
ResetDelayTimer(&data->stateAdvanceDelay);
@@ -334,7 +334,7 @@ static void Task_EReaderComm(u8 taskId)
}
break;
case 7:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_LinkIsIncorrect))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_LinkIsIncorrect))
data->state = 4;
break;
case 8:
@@ -451,19 +451,19 @@ static void Task_EReaderComm(u8 taskId)
data->state = 26;
break;
case 23:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_CardReadingHasBeenHalted))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_CardReadingHasBeenHalted))
data->state = 26;
break;
case 20:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_ConnectionErrorCheckLink))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_ConnectionErrorCheckLink))
data->state = 0;
break;
case 21:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_ConnectionErrorTryAgain))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_ConnectionErrorTryAgain))
data->state = 0;
break;
case 22:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textOrReceiveState, gJPText_WriteErrorUnableToSaveData))
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_WriteErrorUnableToSaveData))
data->state = 0;
break;
case 26:
@@ -943,12 +943,12 @@ u16 MEvent_GetBattleCardCount(u32 command)
return 0;
}
void ResetReceivedWonderCardFlag(void)
void MysteryGift_DisableStats(void)
{
sReceivedWonderCardIsValid = FALSE;
}
bool32 MEventHandleReceivedWonderCard(u16 flagId)
bool32 MysteryGift_TryEnableStatsByFlagId(u16 flagId)
{
sReceivedWonderCardIsValid = FALSE;
if (flagId == 0)
+27 -48
View File
@@ -354,7 +354,7 @@ void vblankcb_mystery_gift_e_reader_run(void)
TransferPlttBuffer();
}
void c2_mystery_gift_e_reader_run(void)
void CB2_MysteryGiftEReader(void)
{
RunTasks();
RunTextPrinters();
@@ -434,7 +434,7 @@ void c2_mystery_gift(void)
{
if (HandleMysteryGiftOrEReaderSetup(0))
{
SetMainCallback2(c2_mystery_gift_e_reader_run);
SetMainCallback2(CB2_MysteryGiftEReader);
gGiftIsFromEReader = FALSE;
task_add_00_mystery_gift();
}
@@ -444,7 +444,7 @@ void c2_ereader(void)
{
if (HandleMysteryGiftOrEReaderSetup(1))
{
SetMainCallback2(c2_mystery_gift_e_reader_run);
SetMainCallback2(CB2_MysteryGiftEReader);
gGiftIsFromEReader = TRUE;
task_add_00_ereader();
}
@@ -540,7 +540,7 @@ void ClearTextWindow(void)
CopyWindowToVram(1, COPYWIN_MAP);
}
bool32 MG_PrintTextOnWindow1AndWaitButton(u8 *textState, const u8 *str)
bool32 PrintMysteryGiftMenuMessage(u8 *textState, const u8 *str)
{
switch (*textState)
{
@@ -650,7 +650,7 @@ u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu)
return response;
}
s8 mevent_message_print_and_prompt_yes_no(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
s8 DoMysteryGiftYesNo(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
{
struct WindowTemplate windowTemplate;
s8 input;
@@ -878,25 +878,17 @@ bool32 TearDownCardOrNews_ReturnToTopMenu(bool32 cardOrNews, bool32 arg1)
s32 mevent_message_prompt_discard(u8 * textState, u16 * windowId, bool32 cardOrNews)
{
if (cardOrNews == 0)
{
return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
}
return DoMysteryGiftYesNo(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
else
{
return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_OkayToDiscardNews);
}
return DoMysteryGiftYesNo(textState, windowId, TRUE, gText_OkayToDiscardNews);
}
bool32 mevent_message_was_thrown_away(u8 * textState, bool32 cardOrNews)
{
if (cardOrNews == 0)
{
return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderCardThrownAway);
}
return PrintMysteryGiftMenuMessage(textState, gText_WonderCardThrownAway);
else
{
return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderNewsThrownAway);
}
return PrintMysteryGiftMenuMessage(textState, gText_WonderNewsThrownAway);
}
bool32 mevent_save_game(u8 * state)
@@ -1098,7 +1090,7 @@ static bool32 PrintMGSendStatus(u8 * state, u16 * arg1, u8 arg2, u32 msgId)
}
else
{
return MG_PrintTextOnWindow1AndWaitButton(state, str);
return PrintMysteryGiftMenuMessage(state, str);
}
}
@@ -1165,7 +1157,7 @@ void task00_mystery_gift(u8 taskId)
{
if (data->IsCardOrNews == 0)
{
if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveCardNewOneInput))
if (PrintMysteryGiftMenuMessage(&data->textState, gText_DontHaveCardNewOneInput))
{
data->state = 3;
PrintMysteryGiftOrEReaderTopMenu(0, 1);
@@ -1173,7 +1165,7 @@ void task00_mystery_gift(u8 taskId)
}
else
{
if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveNewsNewOneInput))
if (PrintMysteryGiftMenuMessage(&data->textState, gText_DontHaveNewsNewOneInput))
{
data->state = 3;
PrintMysteryGiftOrEReaderTopMenu(0, 1);
@@ -1228,23 +1220,15 @@ void task00_mystery_gift(u8 taskId)
{
case 0:
if (data->source == 1)
{
MEvent_CreateTask_CardOrNewsWithFriend(ACTIVITY_WCARD2);
}
CreateTask_LinkMysteryGiftWithFriend(ACTIVITY_WONDER_CARD);
else if (data->source == 0)
{
MEvent_CreateTask_CardOrNewsOverWireless(ACTIVITY_WCARD2);
}
CreateTask_LinkMysteryGiftOverWireless(ACTIVITY_WONDER_CARD);
break;
case 1:
if (data->source == 1)
{
MEvent_CreateTask_CardOrNewsWithFriend(ACTIVITY_WNEWS2);
}
CreateTask_LinkMysteryGiftWithFriend(ACTIVITY_WONDER_NEWS);
else if (data->source == 0)
{
MEvent_CreateTask_CardOrNewsOverWireless(ACTIVITY_WNEWS2);
}
CreateTask_LinkMysteryGiftOverWireless(ACTIVITY_WONDER_NEWS);
break;
}
data->state = 6;
@@ -1291,7 +1275,7 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 9:
flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, mevent_client_get_buffer());
flag = DoMysteryGiftYesNo(&data->textState, &data->curPromptWindowId, FALSE, mevent_client_get_buffer());
switch (flag)
{
case 0:
@@ -1312,14 +1296,14 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 10:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, mevent_client_get_buffer()))
if (PrintMysteryGiftMenuMessage(&data->textState, mevent_client_get_buffer()))
{
mevent_client_inc_flag();
data->state = 7;
}
break;
case 11:
flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_ThrowAwayWonderCard);
flag = DoMysteryGiftYesNo(&data->textState, &data->curPromptWindowId, FALSE, gText_ThrowAwayWonderCard);
switch (flag)
{
case 0:
@@ -1347,7 +1331,7 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 12:
flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_HaventReceivedCardsGift);
flag = DoMysteryGiftYesNo(&data->textState, &data->curPromptWindowId, FALSE, gText_HaventReceivedCardsGift);
switch (flag)
{
case 0:
@@ -1387,17 +1371,12 @@ void task00_mystery_gift(u8 taskId)
case 15:
r1 = mevent_message(&sp0, data->IsCardOrNews, data->source, data->prevPromptWindowId);
if (r1 == NULL)
{
r1 = data->buffer;
}
if (sp0)
{
flag = PrintMGSuccessMessage(&data->textState, r1, &data->curPromptWindowId);
}
else
{
flag = MG_PrintTextOnWindow1AndWaitButton(&data->textState, r1);
}
flag = PrintMysteryGiftMenuMessage(&data->textState, r1);
if (flag)
{
if (data->prevPromptWindowId == 3)
@@ -1423,7 +1402,7 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 16:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
if (PrintMysteryGiftMenuMessage(&data->textState, gText_CommunicationError))
{
data->state = 0;
PrintMysteryGiftOrEReaderTopMenu(0, 0);
@@ -1536,7 +1515,7 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 23:
switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, TRUE, gText_HaventReceivedGiftOkayToDiscard))
switch ((u32)DoMysteryGiftYesNo(&data->textState, &data->curPromptWindowId, TRUE, gText_HaventReceivedGiftOkayToDiscard))
{
case 0:
data->state = 24;
@@ -1587,10 +1566,10 @@ void task00_mystery_gift(u8 taskId)
switch (data->IsCardOrNews)
{
case 0:
MEvent_CreateTask_Leader(ACTIVITY_WCARD2);
CreateTask_SendMysteryGift(ACTIVITY_WONDER_CARD);
break;
case 1:
MEvent_CreateTask_Leader(ACTIVITY_WNEWS2);
CreateTask_SendMysteryGift(ACTIVITY_WONDER_NEWS);
break;
}
data->source = 1;
@@ -1660,7 +1639,7 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 36:
if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
if (PrintMysteryGiftMenuMessage(&data->textState, gText_CommunicationError))
{
data->state = 0;
PrintMysteryGiftOrEReaderTopMenu(0, 0);
+1 -1
View File
@@ -3239,7 +3239,7 @@ bool32 IsSendingKeysOverCable(void)
static u32 GetLinkSendQueueLength(void)
{
if (gWirelessCommType != 0)
return Rfu.sendQueue.count;
return gRfu.sendQueue.count;
else
return gLink.sendQueue.count;
}
+2 -2
View File
@@ -3851,7 +3851,7 @@ static void CursorCB_Register(u8 taskId)
u16 species = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
u8 isEventLegal = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_EVENT_LEGAL);
switch (CanRegisterMonForTradingBoard(*(struct GFtgtGnameSub *)GetHostRFUtgtGname(), species2, species, isEventLegal))
switch (CanRegisterMonForTradingBoard(*(struct RfuGameCompatibilityData *)GetHostRfuGameData(), species2, species, isEventLegal))
{
case CANT_REGISTER_MON:
StringExpandPlaceholders(gStringVar4, gText_PkmnCantBeTradedNow);
@@ -3877,7 +3877,7 @@ static void CursorCB_Trade1(u8 taskId)
u16 species2 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES2);
u16 species = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
u8 isEventLegal = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_EVENT_LEGAL);
u32 stringId = GetUnionRoomTradeMessageId(*(struct GFtgtGnameSub *)GetHostRFUtgtGname(), gPartnerTgtGnameSub, species2, gUnionRoomOfferedSpecies, gUnionRoomRequestedMonType, species, isEventLegal);
u32 stringId = GetUnionRoomTradeMessageId(*(struct RfuGameCompatibilityData *)GetHostRfuGameData(), gRfuPartnerCompatibilityData, species2, gUnionRoomOfferedSpecies, gUnionRoomRequestedMonType, species, isEventLegal);
if (stringId != UR_TRADE_MSG_NONE)
{
+10 -7
View File
@@ -34,6 +34,7 @@
#include "constants/trainers.h"
#include "constants/hold_effects.h"
#include "constants/battle_move_effects.h"
#include "constants/union_room.h"
#define SPECIES_TO_HOENN(name) [SPECIES_##name - 1] = HOENN_DEX_##name
#define SPECIES_TO_NATIONAL(name) [SPECIES_##name - 1] = NATIONAL_DEX_##name
@@ -1643,7 +1644,9 @@ static const u16 sDeoxysBaseStats[] =
};
#endif
const u16 gLinkPlayerFacilityClasses[] =
// The classes used by other players in the Union Room.
// These should correspond with the overworld graphics in sUnionRoomObjGfxIds
const u16 gUnionRoomFacilityClasses[NUM_UNION_ROOM_CLASSES * GENDER_COUNT] =
{
// Male
FACILITY_CLASS_COOLTRAINER_M,
@@ -6031,19 +6034,19 @@ void SetDeoxysStats(void)
u16 GetUnionRoomTrainerPic(void)
{
u8 linkId = GetMultiplayerId() ^ 1;
u32 arrId = gLinkPlayers[linkId].trainerId & 7;
arrId |= gLinkPlayers[linkId].gender << 3;
return FacilityClassToPicIndex(gLinkPlayerFacilityClasses[arrId]);
u32 arrId = gLinkPlayers[linkId].trainerId % NUM_UNION_ROOM_CLASSES;
arrId |= gLinkPlayers[linkId].gender * NUM_UNION_ROOM_CLASSES;
return FacilityClassToPicIndex(gUnionRoomFacilityClasses[arrId]);
}
u16 GetUnionRoomTrainerClass(void)
{
u8 linkId = GetMultiplayerId() ^ 1;
u32 arrId = gLinkPlayers[linkId].trainerId & 7;
arrId |= gLinkPlayers[linkId].gender << 3;
return gFacilityClassToTrainerClass[gLinkPlayerFacilityClasses[arrId]];
u32 arrId = gLinkPlayers[linkId].trainerId % NUM_UNION_ROOM_CLASSES;
arrId |= gLinkPlayers[linkId].gender * NUM_UNION_ROOM_CLASSES;
return gFacilityClassToTrainerClass[gUnionRoomFacilityClasses[arrId]];
}
void CreateEventLegalEnemyMon(void)
+1 -1
View File
@@ -2540,7 +2540,7 @@ static int GetPlayersAtJumpPeak(void)
static bool32 AreLinkQueuesEmpty(void)
{
return !Rfu.recvQueue.count && !Rfu.sendQueue.count;
return !gRfu.recvQueue.count && !gRfu.sendQueue.count;
}
static int GetNumPlayersForBonus(u8 *arg0)
-663
View File
@@ -1,663 +0,0 @@
#include "global.h"
#include "event_data.h"
#include "event_object_movement.h"
#include "field_player_avatar.h"
#include "fieldmap.h"
#include "rfu_union_tool.h"
#include "script.h"
#include "task.h"
#include "constants/event_object_movement.h"
#include "constants/union_room.h"
#include "constants/event_objects.h"
static EWRAM_DATA struct UnionObj * UnionObjWork = NULL;
static EWRAM_DATA u32 sUnionObjRefreshTimer = 0;
static u8 StartUnionObjAnimTask(void);
static u32 RfuUnionGroupMemberIsInvisible(u32 group, u32 member);
static void UnionPartnerObjectSetFacing(s32 member, s32 group, u8 direction);
static const u8 sUnionObjectEventGfxIds[][10] = {
[MALE] = {
OBJ_EVENT_GFX_COOLTRAINER_M,
OBJ_EVENT_GFX_BLACKBELT,
OBJ_EVENT_GFX_CAMPER,
OBJ_EVENT_GFX_YOUNGSTER,
OBJ_EVENT_GFX_BOY,
OBJ_EVENT_GFX_BUG_CATCHER,
OBJ_EVENT_GFX_MAN,
OBJ_EVENT_GFX_ROCKER
},
[FEMALE] = {
OBJ_EVENT_GFX_COOLTRAINER_F,
OBJ_EVENT_GFX_CHANNELER,
OBJ_EVENT_GFX_PICNICKER,
OBJ_EVENT_GFX_LASS,
OBJ_EVENT_GFX_WOMAN_1,
OBJ_EVENT_GFX_BATTLE_GIRL,
OBJ_EVENT_GFX_WOMAN_2,
OBJ_EVENT_GFX_BEAUTY
}
};
static const s16 sUnionPartnerCoords[][2] = {
{ 4, 6},
{13, 8},
{10, 6},
{ 1, 8},
{13, 4},
{ 7, 4},
{ 1, 4},
{ 7, 8}
};
static const s8 sFacingDirectionOffsets[][2] = {
[DIR_NONE] = { 0, 0},
[DIR_SOUTH] = { 1, 0},
[DIR_NORTH] = { 0, -1},
[DIR_WEST] = {-1, 0},
[DIR_EAST] = { 0, 1}
};
static const u8 sOppositeFacingDirection[] = {
[DIR_NONE] = DIR_NONE,
[DIR_SOUTH] = DIR_NORTH,
[DIR_NORTH] = DIR_SOUTH,
[DIR_WEST] = DIR_EAST,
[DIR_EAST] = DIR_WEST
};
static const u8 sUnionGroupMemberFacings[] = {
DIR_SOUTH,
DIR_WEST,
DIR_SOUTH,
DIR_EAST,
DIR_NORTH
};
static const u8 sUnionRoomLocalIds[] = {
9,
8,
7,
2,
6,
5,
4,
3
};
// Unused
static const u16 sHidePlayerFlags[] = {
FLAG_HIDE_UNION_ROOM_PLAYER_1,
FLAG_HIDE_UNION_ROOM_PLAYER_2,
FLAG_HIDE_UNION_ROOM_PLAYER_3,
FLAG_HIDE_UNION_ROOM_PLAYER_4,
FLAG_HIDE_UNION_ROOM_PLAYER_5,
FLAG_HIDE_UNION_ROOM_PLAYER_6,
FLAG_HIDE_UNION_ROOM_PLAYER_7,
FLAG_HIDE_UNION_ROOM_PLAYER_8
};
static bool32 is_walking_or_running(void)
{
if (gPlayerAvatar.tileTransitionState == 2 || gPlayerAvatar.tileTransitionState == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
static u8 GetUnionRoomPlayerGraphicsId(u32 gender, u32 id)
{
return sUnionObjectEventGfxIds[gender][id % 8];
}
static void GetUnionRoomPlayerFacingCoords(u32 group, u32 member, s32 * xp, s32 * yp)
{
*xp = sUnionPartnerCoords[group][0] + sFacingDirectionOffsets[member][0] + 7;
*yp = sUnionPartnerCoords[group][1] + sFacingDirectionOffsets[member][1] + 7;
}
static bool32 IsUnionRoomPlayerFacingTileAt(u32 group, u32 member, s32 x, s32 y)
{
if (sUnionPartnerCoords[group][0] + sFacingDirectionOffsets[member][0] + 7 != x)
{
return FALSE;
}
else if (sUnionPartnerCoords[group][1] + sFacingDirectionOffsets[member][1] + 7 != y)
{
return FALSE;
}
else
{
return TRUE;
}
}
static bool32 IsUnionRoomPlayerHidden(u32 player_idx)
{
return FlagGet(FLAG_HIDE_UNION_ROOM_PLAYER_1 + player_idx);
}
static void HideUnionRoomPlayer(u32 player_idx)
{
FlagSet(FLAG_HIDE_UNION_ROOM_PLAYER_1 + player_idx);
}
static void ShowUnionRoomPlayer(u32 player_idx)
{
FlagClear(FLAG_HIDE_UNION_ROOM_PLAYER_1 + player_idx);
}
static void SetUnionRoomPlayerGfx(u32 playerIdx, u32 gfxId)
{
VarSet(VAR_OBJ_GFX_ID_0 + playerIdx, gfxId);
}
static void CreateUnionRoomPlayerObjectEvent(u32 playerIdx)
{
TrySpawnObjectEvent(sUnionRoomLocalIds[playerIdx], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
}
static void RemoveUnionRoomPlayerObjectEvent(u32 playerIdx)
{
RemoveObjectEventByLocalIdAndMap(sUnionRoomLocalIds[playerIdx], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
}
static bool32 SetUnionRoomPlayerEnterExitMovement(u32 playerIdx, const u8 * movement)
{
u8 objectId;
struct ObjectEvent * object;
if (TryGetObjectEventIdByLocalIdAndMap(sUnionRoomLocalIds[playerIdx], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &objectId))
{
return FALSE;
}
object = &gObjectEvents[objectId];
if (ObjectEventIsMovementOverridden(object))
{
return FALSE;
}
if (ObjectEventSetHeldMovement(object, *movement))
{
AGB_ASSERT_EX(0, ABSPATH("rfu_union_tool.c"), 387);
return FALSE;
}
return TRUE;
}
static bool32 TryReleaseUnionRoomPlayerObjectEvent(u32 playerIdx)
{
u8 objectId;
struct ObjectEvent * object;
if (TryGetObjectEventIdByLocalIdAndMap(sUnionRoomLocalIds[playerIdx], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &objectId))
{
return TRUE;
}
object = &gObjectEvents[objectId];
if (!ObjectEventClearHeldMovementIfFinished(object))
{
return FALSE;
}
if (!ArePlayerFieldControlsLocked())
{
UnfreezeObjectEvent(object);
}
else
{
FreezeObjectEvent(object);
}
return TRUE;
}
u8 ZeroUnionObjWork(struct UnionObj * ptr)
{
s32 i;
sUnionObjRefreshTimer = 0;
UnionObjWork = ptr;
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 442)
for (i = 0; i < 8; i++)
{
ptr[i].state = 0;
ptr[i].gfxId = 0;
ptr[i].animState = 0;
ptr[i].schedAnim = 0;
}
return StartUnionObjAnimTask();
}
static const u8 sMovement_UnionPlayerExit[2] = {
MOVEMENT_ACTION_FLY_UP,
MOVEMENT_ACTION_STEP_END
};
static bool32 AnimateUnionRoomPlayerDespawn(s8 * a0, u32 playerIdx, struct UnionObj * ptr)
{
switch (*a0)
{
case 0:
if (SetUnionRoomPlayerEnterExitMovement(playerIdx, sMovement_UnionPlayerExit) == TRUE)
{
HideUnionRoomPlayer(playerIdx);
(*a0)++;
}
break;
case 1:
if (TryReleaseUnionRoomPlayerObjectEvent(playerIdx))
{
RemoveUnionRoomPlayerObjectEvent(playerIdx);
HideUnionRoomPlayer(playerIdx);
*a0 = 0;
return TRUE;
}
break;
}
return FALSE;
}
static const u8 sMovement_UnionPlayerEnter[2] = {
MOVEMENT_ACTION_FLY_DOWN,
MOVEMENT_ACTION_STEP_END
};
static bool32 AnimateUnionRoomPlayerSpawn(s8 * state_p, u32 playerIdx, struct UnionObj * ptr)
{
s16 x, y;
switch (*state_p)
{
case 0:
if (!is_walking_or_running())
{
break;
}
PlayerGetDestCoords(&x, &y);
if (IsUnionRoomPlayerFacingTileAt(playerIdx, 0, x, y) == TRUE)
{
break;
}
player_get_pos_including_state_based_drift(&x, &y);
if (IsUnionRoomPlayerFacingTileAt(playerIdx, 0, x, y) == TRUE)
{
break;
}
SetUnionRoomPlayerGfx(playerIdx, ptr->gfxId);
CreateUnionRoomPlayerObjectEvent(playerIdx);
ShowUnionRoomPlayer(playerIdx);
(*state_p)++;
// fallthrough
case 3: // incorrect?
if (SetUnionRoomPlayerEnterExitMovement(playerIdx, sMovement_UnionPlayerEnter) == 1)
{
(*state_p)++;
}
break;
case 2:
if (TryReleaseUnionRoomPlayerObjectEvent(playerIdx))
{
*state_p = 0;
return TRUE;
}
break;
}
return FALSE;
}
static bool32 SpawnGroupLeader(u32 playerIdx, u32 gender, u32 idMod256)
{
struct UnionObj * ptr = &UnionObjWork[playerIdx];
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 561)
ptr->schedAnim = UNION_ROOM_SPAWN_IN;
ptr->gfxId = GetUnionRoomPlayerGraphicsId(gender, idMod256);
if (ptr->state == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
static bool32 DespawnGroupLeader(u32 playerIdx)
{
struct UnionObj * ptr = &UnionObjWork[playerIdx];
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 577)
ptr->schedAnim = UNION_ROOM_SPAWN_OUT;
if (ptr->state == 1)
{
return TRUE;
}
else
{
return FALSE;
}
}
static void AnimateUnionObj(u32 playerIdx, struct UnionObj * ptr)
{
switch (ptr->state)
{
case 0:
if (ptr->schedAnim == UNION_ROOM_SPAWN_IN)
{
ptr->state = 2;
ptr->animState = 0;
}
else
{
break;
}
// fallthrough
case 2:
if (!RfuUnionGroupMemberIsInvisible(playerIdx, 0) && ptr->schedAnim == 2)
{
ptr->state = 0;
ptr->animState = 0;
RemoveUnionRoomPlayerObjectEvent(playerIdx);
HideUnionRoomPlayer(playerIdx);
}
else if (AnimateUnionRoomPlayerSpawn(&ptr->animState, playerIdx, ptr) == TRUE)
{
ptr->state = 1;
}
break;
case 1:
if (ptr->schedAnim == UNION_ROOM_SPAWN_OUT)
{
ptr->state = 3;
ptr->animState = 0;
}
else
{
break;
}
// fallthrough
case 3:
if (AnimateUnionRoomPlayerDespawn(&ptr->animState, playerIdx, ptr) == TRUE)
{
ptr->state = 0;
}
break;
}
ptr->schedAnim = UNION_ROOM_SPAWN_NONE;
}
static void Task_AnimateUnionObjs(u8 taskId)
{
s32 i;
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 643)
for (i = 0; i < 8; i++)
{
AnimateUnionObj(i, &UnionObjWork[i]);
}
}
static u8 StartUnionObjAnimTask(void)
{
if (FuncIsActiveTask(Task_AnimateUnionObjs) == TRUE)
{
AGB_ASSERT_EX(0, ABSPATH("rfu_union_tool.c"), 655)
return NUM_TASKS;
}
else
{
return CreateTask(Task_AnimateUnionObjs, 5);
}
}
static void DestroyAnimateUnionObjsTask(void)
{
u8 taskId = FindTaskIdByFunc(Task_AnimateUnionObjs);
if (taskId < NUM_TASKS)
{
DestroyTask(taskId);
}
}
void DeleteUnionObjWorkAndStopTask(void)
{
s32 i;
for (i = 0; i < 8; i++)
{
if (!IsUnionRoomPlayerHidden(i))
{
RemoveUnionRoomPlayerObjectEvent(i);
HideUnionRoomPlayer(i);
}
}
UnionObjWork = NULL;
DestroyAnimateUnionObjsTask();
}
void CreateGroupMemberObjectsInvisible(u8 * sprite_ids, s32 group)
{
s32 i;
for (i = 0; i < 5; i++)
{
s32 obj_id = 5 * group + i;
sprite_ids[obj_id] = CreateVirtualObject(OBJ_EVENT_GFX_MAN, obj_id - 0x38, sUnionPartnerCoords[group][0] + sFacingDirectionOffsets[i][0], sUnionPartnerCoords[group][1] + sFacingDirectionOffsets[i][1], 3, 1);
SetVirtualObjectInvisibility(obj_id - 0x38, TRUE);
}
}
void DestroyGroupMemberObjects(u8 *spriteIds)
{
s32 i;
for (i = 0; i < 40; i++)
{
DestroySprite(&gSprites[spriteIds[i]]);
}
}
void MakeGroupAssemblyAreasPassable(void)
{
s32 i, j, x, y;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 5; j++)
{
GetUnionRoomPlayerFacingCoords(i, j, &x, &y);
MapGridSetMetatileImpassabilityAt(x, y, FALSE);
}
}
}
static u8 UnionPartnerObjectGetFacing(u32 member, u32 group, struct GFtgtGname * gname)
{
if (member != 0)
{
return sUnionGroupMemberFacings[member];
}
else if (gname->activity == 0x45)
{
return DIR_SOUTH;
}
else
{
return DIR_EAST;
}
}
static u32 RfuUnionGroupMemberIsInvisible(u32 group, u32 member)
{
return IsVirtualObjectInvisible(5 * group + member - 0x38);
}
static void SpawnGroupMember(u32 groupNo, u32 memberNo, u8 direction, struct GFtgtGname * gname)
{
s32 x, y;
s32 objId = 5 * groupNo + memberNo;
if (RfuUnionGroupMemberIsInvisible(groupNo, memberNo) == TRUE)
{
SetVirtualObjectInvisibility(objId - 0x38, FALSE);
SetVirtualObjectSpriteAnim(objId - 0x38, UNION_ROOM_SPAWN_IN);
}
SetVirtualObjectGraphics(objId - 0x38, direction);
UnionPartnerObjectSetFacing(memberNo, groupNo, UnionPartnerObjectGetFacing(memberNo, groupNo, gname));
GetUnionRoomPlayerFacingCoords(groupNo, memberNo, &x, &y);
MapGridSetMetatileImpassabilityAt(x, y, TRUE);
}
static void DespawnGroupMember(u32 group, u32 member)
{
s32 x, y;
SetVirtualObjectSpriteAnim(5 * group + member - 0x38, UNION_ROOM_SPAWN_OUT);
GetUnionRoomPlayerFacingCoords(group, member, &x, &y);
MapGridSetMetatileImpassabilityAt(x, y, FALSE);
}
static void AssembleGroup(u32 group, struct GFtgtGname * gname)
{
s16 x, y, x2, y2;
s32 i;
PlayerGetDestCoords(&x, &y);
player_get_pos_including_state_based_drift(&x2, &y2);
if (IsVirtualObjectInvisible(5 * group - 0x38) == TRUE)
{
if (IsUnionRoomPlayerFacingTileAt(group, 0, x, y) == TRUE || IsUnionRoomPlayerFacingTileAt(group, 0, x2, y2) == TRUE)
{
return;
}
SpawnGroupMember(group, 0, GetUnionRoomPlayerGraphicsId(gname->playerGender, gname->unk_00.playerTrainerId[0]), gname);
}
for (i = 1; i < 5; i++)
{
if (gname->child_sprite_gender[i - 1] == 0)
{
DespawnGroupMember(group, i);
}
else if (IsUnionRoomPlayerFacingTileAt(group, i, x, y) == FALSE && IsUnionRoomPlayerFacingTileAt(group, i, x2, y2) == FALSE)
{
SpawnGroupMember(group, i, GetUnionRoomPlayerGraphicsId((gname->child_sprite_gender[i - 1] >> 3) & 1, gname->child_sprite_gender[i - 1] & 7), gname);
}
}
}
static void SpawnGroupLeaderAndMembers(u32 group, struct GFtgtGname * gname)
{
u32 i;
switch (gname->activity)
{
case 0x40:
case 0x54:
SpawnGroupLeader(group, gname->playerGender, gname->unk_00.playerTrainerId[0]);
for (i = 0; i < 5; i++)
{
DespawnGroupMember(group, i);
}
break;
case 0x41:
case 0x44:
case 0x45:
case 0x48:
case 0x51:
case 0x52:
case 0x53:
DespawnGroupLeader(group);
AssembleGroup(group, gname);
break;
default:
AGB_ASSERT_EX(0, ABSPATH("rfu_union_tool.c"), 979)
}
}
static void DespawnGroupLeaderAndMembers(u32 group, struct GFtgtGname * gname)
{
s32 i;
DespawnGroupLeader(group);
for (i = 0; i < 5; i++)
{
DespawnGroupMember(group, i);
}
}
static void UpdateUnionRoomPlayerSprites(struct UnkStruct_URoom * groups)
{
s32 i;
struct UnkStruct_x20 * x20_p;
sUnionObjRefreshTimer = 0;
for (i = 0, x20_p = groups->field_0->arr; i < 8; i++)
{
if (x20_p[i].groupScheduledAnim == UNION_ROOM_SPAWN_IN)
{
SpawnGroupLeaderAndMembers(i, &x20_p[i].gname_uname.gname);
}
else if (x20_p[i].groupScheduledAnim == UNION_ROOM_SPAWN_OUT)
{
DespawnGroupLeaderAndMembers(i, &x20_p[i].gname_uname.gname);
}
}
}
void ScheduleUnionRoomPlayerRefresh(struct UnkStruct_URoom *uroom_p)
{
sUnionObjRefreshTimer = 300;
}
void HandleUnionRoomPlayerRefresh(struct UnkStruct_URoom *uroom_p)
{
if (++sUnionObjRefreshTimer > 300)
{
UpdateUnionRoomPlayerSprites(uroom_p);
}
}
bool32 RfuUnionTool_GetGroupAndMemberInFrontOfPlayer(struct UnkStruct_Main0 *main0_p, s16 *member_p, s16 *group_p, u8 *spriteIds)
{
s16 x, y;
s32 i, j;
struct UnkStruct_x20 * x20_p;
if (!is_walking_or_running())
{
return FALSE;
}
GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
for (i = 0, x20_p = main0_p->arr; i < 8; i++)
{
for (j = 0; j < 5; j++)
{
s32 objId = 5 * i + j;
if (x != sUnionPartnerCoords[i][0] + sFacingDirectionOffsets[j][0] + 7)
{
continue;
}
if (y != sUnionPartnerCoords[i][1] + sFacingDirectionOffsets[j][1] + 7)
{
continue;
}
if (IsVirtualObjectInvisible(objId - 0x38) != FALSE)
{
continue;
}
if (IsVirtualObjectAnimating(objId - 0x38) != FALSE)
{
continue;
}
if (x20_p[i].groupScheduledAnim != UNION_ROOM_SPAWN_IN)
{
continue;
}
UnionPartnerObjectSetFacing(j, i, sOppositeFacingDirection[GetPlayerFacingDirection()]);
*member_p = j;
*group_p = i;
return TRUE;
}
}
return FALSE;
}
static void UnionPartnerObjectSetFacing(s32 member, s32 group, u8 direction)
{
TurnVirtualObject(5 * group - 0x38 + member, direction);
}
void UpdateUnionGroupMemberFacing(u32 member, u32 group, struct UnkStruct_Main0 *main0_p)
{
return UnionPartnerObjectSetFacing(member, group, UnionPartnerObjectGetFacing(member, group, &main0_p->arr[group].gname_uname.gname));
}
+1 -1
View File
@@ -374,7 +374,7 @@ void Task_StartMenuHandleInput(u8 taskId)
{
case 0:
if (InUnionRoom() == TRUE)
var_800D_set_xB();
SetUsingUnionRoomStartMenu();
sStartMenuCallback = StartCB_HandleInput;
data[0]++;
break;
+10 -10
View File
@@ -711,7 +711,7 @@ static void InitTradeMenuResources(void)
}
}
void CB2_ReturnFromLinkTrade(void)
void CB2_StartCreateTradeMenu(void)
{
SetMainCallback2(CB2_ReturnFromLinkTrade2);
}
@@ -759,7 +759,7 @@ static void CB2_ReturnFromLinkTrade2(void)
{
SetWirelessCommType1();
OpenLink();
LinkRfu_CreateIdleTask();
CreateTask_RfuIdle();
}
else
{
@@ -802,13 +802,13 @@ static void CB2_ReturnFromLinkTrade2(void)
case 4:
if (gReceivedRemoteLinkPlayers == TRUE && IsLinkPlayerDataExchangeComplete() == TRUE)
{
LinkRfu_DestroyIdleTask();
DestroyTask_RfuIdle();
CalculatePlayerPartyCount();
gMain.state++;
sTradeMenuResourcesPtr->loadUISpritesState = 0;
if (gWirelessCommType)
{
ToggleLMANlinkRecovery(TRUE);
Rfu_SetLinkRecovery(TRUE);
SetLinkStandbyCallback();
}
}
@@ -1208,7 +1208,7 @@ static void TradeMenuCB_10(void)
static void TradeMenuCB_13(void)
{
gMain.savedCallback = CB2_ReturnFromLinkTrade;
gMain.savedCallback = CB2_StartCreateTradeMenu;
if (gWirelessCommType != 0)
{
if (IsLinkRfuTaskFinished())
@@ -1218,7 +1218,7 @@ static void TradeMenuCB_13(void)
Free(sTradeMenuResourcesPtr);
gMain.callback1 = NULL;
DestroyWirelessStatusIndicatorSprite();
SetMainCallback2(CB2_InitTradeAnim_LinkTrade);
SetMainCallback2(CB2_LinkTrade);
}
}
else
@@ -1229,7 +1229,7 @@ static void TradeMenuCB_13(void)
FreeAllWindowBuffers();
Free(sTradeMenuResourcesPtr);
gMain.callback1 = NULL;
SetMainCallback2(CB2_InitTradeAnim_LinkTrade);
SetMainCallback2(CB2_LinkTrade);
}
}
}
@@ -2019,7 +2019,7 @@ static void TradeMenuCB_12(void)
static void TradeMenuCB_16(void)
{
if (!ToggleLMANlinkRecovery(FALSE))
if (!Rfu_SetLinkRecovery(FALSE))
{
SetLinkStandbyCallback();
sTradeMenuResourcesPtr->tradeMenuCBnum = 13;
@@ -2720,7 +2720,7 @@ static bool32 IsDeoxysOrMewUntradable(u16 species, bool8 isEventLegal)
return FALSE;
}
int GetUnionRoomTradeMessageId(struct GFtgtGnameSub playerSub, struct GFtgtGnameSub partnerSub, u16 species1, u16 species2, u8 type, u16 species3, u8 isEventLegal)
int GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData playerSub, struct RfuGameCompatibilityData partnerSub, u16 species1, u16 species2, u8 type, u16 species3, u8 isEventLegal)
{
u8 playerHasNationalDex = playerSub.hasNationalDex;
u8 playerIsChampion = playerSub.isChampion;
@@ -2800,7 +2800,7 @@ int GetUnionRoomTradeMessageId(struct GFtgtGnameSub playerSub, struct GFtgtGname
return 0;
}
int CanRegisterMonForTradingBoard(struct GFtgtGnameSub playerSub, u16 species2, u16 species, u8 isEventLegal)
int CanRegisterMonForTradingBoard(struct RfuGameCompatibilityData playerSub, u16 species2, u16 species, u8 isEventLegal)
{
u8 canTradeEggAndNational = playerSub.hasNationalDex;
+3 -3
View File
@@ -773,7 +773,7 @@ static void LoadTradeMonPic(u8 whichParty, u8 action)
}
}
void CB2_InitTradeAnim_LinkTrade(void)
void CB2_LinkTrade(void)
{
switch (gMain.state)
{
@@ -2668,7 +2668,7 @@ static void CB2_HandleTradeEnded(void)
case 8:
if (IsBGMStopped() == TRUE)
{
if (gWirelessCommType && gMain.savedCallback == CB2_ReturnFromLinkTrade)
if (gWirelessCommType && gMain.savedCallback == CB2_StartCreateTradeMenu)
{
SetLinkStandbyCallback();
}
@@ -2680,7 +2680,7 @@ static void CB2_HandleTradeEnded(void)
}
break;
case 9:
if (gWirelessCommType && gMain.savedCallback == CB2_ReturnFromLinkTrade)
if (gWirelessCommType && gMain.savedCallback == CB2_StartCreateTradeMenu)
{
if (IsLinkRfuTaskFinished())
{
+1560 -1970
View File
File diff suppressed because it is too large Load Diff
+15 -15
View File
@@ -324,7 +324,7 @@ static void ChatEntryRoutine_Join(void)
sWork->routineState++;
// fall through
case 1:
if (IsLinkTaskFinished() && !RfuHasFoundNewLeader())
if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{
if (SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
sWork->routineState++;
@@ -527,14 +527,14 @@ static void ChatEntryRoutine_AskQuitChatting(void)
sWork->routineState = 3;
break;
case 0:
Rfu_UnionRoomChat_StopLinkManager();
Rfu_StopPartnerSearch();
PrepareSendBuffer_Disband(sWork->sendMessageBuffer);
sWork->routineState = 4;
break;
}
break;
case 4:
if (IsLinkTaskFinished() && !RfuHasFoundNewLeader() && SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive() && SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
{
if (sWork->multiplayerId == 0)
sWork->routineState = 6;
@@ -577,15 +577,15 @@ static void ChatEntryRoutine_ExitChat(void)
}
break;
case 3:
if (IsLinkTaskFinished() && !RfuHasFoundNewLeader() && SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive() && SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
sWork->routineState++;
break;
case 4:
if ((GetBlockReceivedStatus() & 1) && !RfuHasFoundNewLeader())
if ((GetBlockReceivedStatus() & 1) && !Rfu_IsPlayerExchangeActive())
sWork->routineState++;
break;
case 5:
if (IsLinkTaskFinished() && !RfuHasFoundNewLeader())
if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{
SetCloseLinkCallback();
sWork->exitDelayTimer = 0;
@@ -620,7 +620,7 @@ static void ChatEntryRoutine_Drop(void)
}
break;
case 1:
if (!RunDisplaySubtask(0) && IsLinkTaskFinished() && !RfuHasFoundNewLeader())
if (!RunDisplaySubtask(0) && IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{
SetCloseLinkCallback();
sWork->exitDelayTimer = 0;
@@ -666,7 +666,7 @@ static void ChatEntryRoutine_Disbanded(void)
}
break;
case 2:
if (RunDisplaySubtask(0) != TRUE && IsLinkTaskFinished() && !RfuHasFoundNewLeader())
if (RunDisplaySubtask(0) != TRUE && IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{
SetCloseLinkCallback();
sWork->exitDelayTimer = 0;
@@ -704,7 +704,7 @@ static void ChatEntryRoutine_SendMessage(void)
sWork->routineState++;
// fall through
case 1:
if (IsLinkTaskFinished() == TRUE && !RfuHasFoundNewLeader() && SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
if (IsLinkTaskFinished() == TRUE && !Rfu_IsPlayerExchangeActive() && SendBlock(0, sWork->sendMessageBuffer, sizeof(sWork->sendMessageBuffer)))
sWork->routineState++;
break;
case 2:
@@ -1144,7 +1144,7 @@ static void PrepareSendBuffer_Leave(u8 *arg0)
arg0[0] = CHAT_MESSAGE_LEAVE;
StringCopy(&arg0[1], gSaveBlock2Ptr->playerName);
arg0[1 + (PLAYER_NAME_LENGTH + 1)] = sWork->multiplayerId;
sub_80FB9D0();
RfuSetNormalDisconnectMode();
}
static void PrepareSendBuffer_Drop(u8 *arg0)
@@ -1355,7 +1355,7 @@ static void Task_ReceiveChatMessage(u8 taskId)
}
tBlockReceivedStatus = GetBlockReceivedStatus();
if (!tBlockReceivedStatus && RfuHasFoundNewLeader())
if (!tBlockReceivedStatus && Rfu_IsPlayerExchangeActive())
return;
tI = 0;
@@ -1409,13 +1409,13 @@ static void Task_ReceiveChatMessage(u8 taskId)
// You're the leader, and the person who left is not you
if (GetLinkPlayerCount() == 2)
{
Rfu_UnionRoomChat_StopLinkManager();
Rfu_StopPartnerSearch();
sWork->exitType = CHATEXIT_LEADER_LAST;
DestroyTask(taskId);
return;
}
sub_80FBD6C(tCurrLinkPlayer);
Rfu_DisconnectPlayerById(tCurrLinkPlayer);
}
tState = 3;
@@ -1433,10 +1433,10 @@ static void Task_ReceiveChatMessage(u8 taskId)
DestroyTask(taskId);
break;
case 2:
if (!RfuHasFoundNewLeader())
if (!Rfu_IsPlayerExchangeActive())
{
if (sWork->multiplayerId == 0)
sub_80FB030(sWork->linkPlayerCount);
SetUnionRoomChatPlayerData(sWork->linkPlayerCount);
tState = 1;
}
+615
View File
@@ -0,0 +1,615 @@
#include "global.h"
#include "event_data.h"
#include "event_object_movement.h"
#include "field_player_avatar.h"
#include "fieldmap.h"
#include "union_room_player_avatar.h"
#include "script.h"
#include "task.h"
#include "constants/event_object_movement.h"
#include "constants/union_room.h"
#include "constants/event_objects.h"
#define UR_SPRITE_START_ID (MAX_SPRITES - MAX_UNION_ROOM_LEADERS)
// Each parent player can lead a group of up to MAX_RFU_PLAYERS (including themselves).
// Multiply the leader's id by MAX_RFU_PLAYERS and add the member's id (0 if the leader) to
// get the sprite index of that player.
#define UR_PLAYER_SPRITE_ID(leaderId, memberId)(MAX_RFU_PLAYERS * leaderId + memberId)
// Original symbol name from ASSERT statements
#define UnionObjWork sUnionObjWork
static EWRAM_DATA struct UnionRoomObject * sUnionObjWork = NULL;
static EWRAM_DATA u32 sUnionObjRefreshTimer = 0;
static u8 CreateTask_AnimateUnionRoomPlayers(void);
static u32 IsUnionRoomPlayerInvisible(u32 leaderId, u32 member);
static void SetUnionRoomObjectFacingDirection(s32 member, s32 leaderId, u8 direction);
// + 2 is just to match, those elements are empty and never read
// Graphics ids should correspond with the classes in gUnionRoomFacilityClasses
static const u8 sUnionRoomObjGfxIds[GENDER_COUNT][NUM_UNION_ROOM_CLASSES + 2] = {
[MALE] = {
OBJ_EVENT_GFX_COOLTRAINER_M,
OBJ_EVENT_GFX_BLACKBELT,
OBJ_EVENT_GFX_CAMPER,
OBJ_EVENT_GFX_YOUNGSTER,
OBJ_EVENT_GFX_BOY,
OBJ_EVENT_GFX_BUG_CATCHER,
OBJ_EVENT_GFX_MAN,
OBJ_EVENT_GFX_ROCKER
},
[FEMALE] = {
OBJ_EVENT_GFX_COOLTRAINER_F,
OBJ_EVENT_GFX_CHANNELER,
OBJ_EVENT_GFX_PICNICKER,
OBJ_EVENT_GFX_LASS,
OBJ_EVENT_GFX_WOMAN_1,
OBJ_EVENT_GFX_BATTLE_GIRL,
OBJ_EVENT_GFX_WOMAN_2,
OBJ_EVENT_GFX_BEAUTY
}
};
static const s16 sUnionRoomPlayerCoords[MAX_UNION_ROOM_LEADERS][2] = {
{ 4, 6},
{13, 8},
{10, 6},
{ 1, 8},
{13, 4},
{ 7, 4},
{ 1, 4},
{ 7, 8}
};
// If there's a group of players interacting in the Union Room, the group
// leader will be at one of the positions above and each member in the group
// will be at one of the offsets from that position below. The leader will
// be at the first offset (0,0), as they're at the center.
static const s8 sUnionRoomGroupOffsets[][2] = {
{ 0, 0}, // Center
{ 1, 0}, // Left
{ 0, -1}, // Top
{-1, 0}, // Right
{ 0, 1} // Bottom
};
static const u8 sOppositeFacingDirection[] = {
[DIR_NONE] = DIR_NONE,
[DIR_SOUTH] = DIR_NORTH,
[DIR_NORTH] = DIR_SOUTH,
[DIR_WEST] = DIR_EAST,
[DIR_EAST] = DIR_WEST
};
// Compare to sUnionRoomGroupOffsets, the direction each group member
// needs to be facing in order to face the group leader in the center.
static const u8 sMemberFacingDirections[] = {
DIR_SOUTH, // Leader, but never read
DIR_WEST,
DIR_SOUTH,
DIR_EAST,
DIR_NORTH
};
static const u8 sUnionRoomLocalIds[] = {
LOCALID_UNION_ROOM_PLAYER_1,
LOCALID_UNION_ROOM_PLAYER_2,
LOCALID_UNION_ROOM_PLAYER_3,
LOCALID_UNION_ROOM_PLAYER_4,
LOCALID_UNION_ROOM_PLAYER_5,
LOCALID_UNION_ROOM_PLAYER_6,
LOCALID_UNION_ROOM_PLAYER_7,
LOCALID_UNION_ROOM_PLAYER_8
};
// Unused
static const u16 sHidePlayerFlags[] = {
FLAG_HIDE_UNION_ROOM_PLAYER_1,
FLAG_HIDE_UNION_ROOM_PLAYER_2,
FLAG_HIDE_UNION_ROOM_PLAYER_3,
FLAG_HIDE_UNION_ROOM_PLAYER_4,
FLAG_HIDE_UNION_ROOM_PLAYER_5,
FLAG_HIDE_UNION_ROOM_PLAYER_6,
FLAG_HIDE_UNION_ROOM_PLAYER_7,
FLAG_HIDE_UNION_ROOM_PLAYER_8
};
static bool32 IsPlayerStandingStill(void)
{
if (gPlayerAvatar.tileTransitionState == T_TILE_CENTER || gPlayerAvatar.tileTransitionState == T_NOT_MOVING)
return TRUE;
else
return FALSE;
}
// Gender and trainer id are used to determine which sprite a player appears as
static u8 GetUnionRoomPlayerGraphicsId(u32 gender, u32 id)
{
return sUnionRoomObjGfxIds[gender][id % NUM_UNION_ROOM_CLASSES];
}
static void GetUnionRoomPlayerCoords(u32 leaderId, u32 memberId, s32 * x, s32 * y)
{
*x = sUnionRoomPlayerCoords[leaderId][0] + sUnionRoomGroupOffsets[memberId][0] + 7;
*y = sUnionRoomPlayerCoords[leaderId][1] + sUnionRoomGroupOffsets[memberId][1] + 7;
}
static bool32 IsUnionRoomPlayerAt(u32 leaderId, u32 memberId, s32 x, s32 y)
{
if ((sUnionRoomPlayerCoords[leaderId][0] + sUnionRoomGroupOffsets[memberId][0] + MAP_OFFSET == x)
&& (sUnionRoomPlayerCoords[leaderId][1] + sUnionRoomGroupOffsets[memberId][1] + MAP_OFFSET == y))
return TRUE;
else
return FALSE;
}
static bool32 IsUnionRoomPlayerHidden(u32 leaderId)
{
return FlagGet(FLAG_HIDE_UNION_ROOM_PLAYER_1 + leaderId);
}
static void HideUnionRoomPlayer(u32 leaderId)
{
FlagSet(FLAG_HIDE_UNION_ROOM_PLAYER_1 + leaderId);
}
static void ShowUnionRoomPlayer(u32 leaderId)
{
FlagClear(FLAG_HIDE_UNION_ROOM_PLAYER_1 + leaderId);
}
static void SetUnionRoomPlayerGfx(u32 leaderId, u32 gfxId)
{
VarSet(VAR_OBJ_GFX_ID_0 + leaderId, gfxId);
}
static void CreateUnionRoomPlayerObjectEvent(u32 leaderId)
{
TrySpawnObjectEvent(sUnionRoomLocalIds[leaderId], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
}
static void RemoveUnionRoomPlayerObjectEvent(u32 leaderId)
{
RemoveObjectEventByLocalIdAndMap(sUnionRoomLocalIds[leaderId], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
}
static bool32 SetUnionRoomPlayerEnterExitMovement(u32 leaderId, const u8 * movement)
{
u8 objectId;
struct ObjectEvent * object;
if (TryGetObjectEventIdByLocalIdAndMap(sUnionRoomLocalIds[leaderId], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &objectId))
return FALSE;
object = &gObjectEvents[objectId];
if (ObjectEventIsMovementOverridden(object))
return FALSE;
if (ObjectEventSetHeldMovement(object, *movement))
{
AGB_ASSERT_EX(0, ABSPATH("rfu_union_tool.c"), 387);
return FALSE;
}
return TRUE;
}
static bool32 TryReleaseUnionRoomPlayerObjectEvent(u32 leaderId)
{
u8 objectId;
struct ObjectEvent * object;
if (TryGetObjectEventIdByLocalIdAndMap(sUnionRoomLocalIds[leaderId], gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &objectId))
return TRUE;
object = &gObjectEvents[objectId];
if (!ObjectEventClearHeldMovementIfFinished(object))
return FALSE;
if (!ArePlayerFieldControlsLocked())
UnfreezeObjectEvent(object);
else
FreezeObjectEvent(object);
return TRUE;
}
u8 InitUnionRoomPlayerObjects(struct UnionRoomObject * players)
{
s32 i;
sUnionObjRefreshTimer = 0;
sUnionObjWork = players;
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 442)
for (i = 0; i < MAX_UNION_ROOM_LEADERS; i++)
{
players[i].state = 0;
players[i].gfxId = 0;
players[i].animState = 0;
players[i].schedAnim = UNION_ROOM_SPAWN_NONE;
}
return CreateTask_AnimateUnionRoomPlayers();
}
static const u8 sMovement_UnionPlayerExit[2] = {
MOVEMENT_ACTION_FLY_UP,
MOVEMENT_ACTION_STEP_END
};
static bool32 AnimateUnionRoomPlayerDespawn(s8 * state, u32 leaderId, struct UnionRoomObject * object)
{
switch (*state)
{
case 0:
if (SetUnionRoomPlayerEnterExitMovement(leaderId, sMovement_UnionPlayerExit) == TRUE)
{
HideUnionRoomPlayer(leaderId);
(*state)++;
}
break;
case 1:
if (TryReleaseUnionRoomPlayerObjectEvent(leaderId))
{
RemoveUnionRoomPlayerObjectEvent(leaderId);
HideUnionRoomPlayer(leaderId);
*state = 0;
return TRUE;
}
break;
}
return FALSE;
}
static const u8 sMovement_UnionPlayerEnter[2] = {
MOVEMENT_ACTION_FLY_DOWN,
MOVEMENT_ACTION_STEP_END
};
static bool32 AnimateUnionRoomPlayerSpawn(s8 * state, u32 leaderId, struct UnionRoomObject * object)
{
s16 x, y;
switch (*state)
{
case 0:
if (!IsPlayerStandingStill())
break;
PlayerGetDestCoords(&x, &y);
if (IsUnionRoomPlayerAt(leaderId, 0, x, y) == TRUE)
break;
player_get_pos_including_state_based_drift(&x, &y);
if (IsUnionRoomPlayerAt(leaderId, 0, x, y) == TRUE)
break;
SetUnionRoomPlayerGfx(leaderId, object->gfxId);
CreateUnionRoomPlayerObjectEvent(leaderId);
ShowUnionRoomPlayer(leaderId);
(*state)++;
// fallthrough
case 3: // incorrect?
if (SetUnionRoomPlayerEnterExitMovement(leaderId, sMovement_UnionPlayerEnter) == 1)
(*state)++;
break;
case 2:
if (TryReleaseUnionRoomPlayerObjectEvent(leaderId))
{
*state = 0;
return TRUE;
}
break;
}
return FALSE;
}
static bool32 SpawnGroupLeader(u32 leaderId, u32 gender, u32 id)
{
struct UnionRoomObject * object = &sUnionObjWork[leaderId];
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 561)
object->schedAnim = UNION_ROOM_SPAWN_IN;
object->gfxId = GetUnionRoomPlayerGraphicsId(gender, id);
if (object->state == 0)
return TRUE;
else
return FALSE;
}
static bool32 DespawnGroupLeader(u32 leaderId)
{
struct UnionRoomObject * object = &sUnionObjWork[leaderId];
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 577)
object->schedAnim = UNION_ROOM_SPAWN_OUT;
if (object->state == 1)
return TRUE;
else
return FALSE;
}
static void AnimateUnionRoomPlayer(u32 leaderId, struct UnionRoomObject * object)
{
switch (object->state)
{
case 0:
if (object->schedAnim == UNION_ROOM_SPAWN_IN)
{
object->state = 2;
object->animState = 0;
}
else
{
break;
}
// fallthrough
case 2:
if (!IsUnionRoomPlayerInvisible(leaderId, 0) && object->schedAnim == UNION_ROOM_SPAWN_OUT)
{
object->state = 0;
object->animState = 0;
RemoveUnionRoomPlayerObjectEvent(leaderId);
HideUnionRoomPlayer(leaderId);
}
else if (AnimateUnionRoomPlayerSpawn(&object->animState, leaderId, object) == TRUE)
{
object->state = 1;
}
break;
case 1:
if (object->schedAnim != UNION_ROOM_SPAWN_OUT)
break;
object->state = 3;
object->animState = 0;
// fallthrough
case 3:
if (AnimateUnionRoomPlayerDespawn(&object->animState, leaderId, object) == TRUE)
object->state = 0;
break;
}
object->schedAnim = UNION_ROOM_SPAWN_NONE;
}
static void Task_AnimateUnionRoomPlayers(u8 taskId)
{
s32 i;
AGB_ASSERT_EX(UnionObjWork != NULL, ABSPATH("rfu_union_tool.c"), 643)
for (i = 0; i < MAX_UNION_ROOM_LEADERS; i++)
AnimateUnionRoomPlayer(i, &sUnionObjWork[i]);
}
static u8 CreateTask_AnimateUnionRoomPlayers(void)
{
if (FuncIsActiveTask(Task_AnimateUnionRoomPlayers) == TRUE)
{
AGB_ASSERT_EX(0, ABSPATH("rfu_union_tool.c"), 655)
return NUM_TASKS;
}
else
{
return CreateTask(Task_AnimateUnionRoomPlayers, 5);
}
}
static void DestroyTask_AnimateUnionRoomPlayers(void)
{
u8 taskId = FindTaskIdByFunc(Task_AnimateUnionRoomPlayers);
if (taskId < NUM_TASKS)
DestroyTask(taskId);
}
void DestroyUnionRoomPlayerObjects(void)
{
s32 i;
for (i = 0; i < MAX_UNION_ROOM_LEADERS; i++)
{
if (!IsUnionRoomPlayerHidden(i))
{
RemoveUnionRoomPlayerObjectEvent(i);
HideUnionRoomPlayer(i);
}
}
sUnionObjWork = NULL;
DestroyTask_AnimateUnionRoomPlayers();
}
void CreateUnionRoomPlayerSprites(u8 * spriteIds, s32 leaderId)
{
s32 memberId;
for (memberId = 0; memberId < MAX_RFU_PLAYERS; memberId++)
{
s32 id = UR_PLAYER_SPRITE_ID(leaderId, memberId);
spriteIds[id] = CreateVirtualObject(OBJ_EVENT_GFX_MAN,
id - UR_SPRITE_START_ID,
sUnionRoomPlayerCoords[leaderId][0] + sUnionRoomGroupOffsets[memberId][0],
sUnionRoomPlayerCoords[leaderId][1] + sUnionRoomGroupOffsets[memberId][1],
3, 1);
SetVirtualObjectInvisibility(id - UR_SPRITE_START_ID, TRUE);
}
}
void DestroyUnionRoomPlayerSprites(u8 *spriteIds)
{
s32 i;
for (i = 0; i < NUM_UNION_ROOM_SPRITES; i++)
DestroySprite(&gSprites[spriteIds[i]]);
}
// Clear the impassable metatiles around the group leaders that get set
// to prevent the player from walking through the group member sprites.
void MakeGroupAssemblyAreasPassable(void)
{
s32 leaderId, memberId, x, y;
for (leaderId = 0; leaderId < MAX_UNION_ROOM_LEADERS; leaderId++)
{
for (memberId = 0; memberId < MAX_RFU_PLAYERS; memberId++)
{
GetUnionRoomPlayerCoords(leaderId, memberId, &x, &y);
MapGridSetMetatileImpassabilityAt(x, y, FALSE);
}
}
}
static u8 GetNewFacingDirectionForUnionRoomPlayer(u32 memberId, u32 leaderId, struct RfuGameData * gameData)
{
if (memberId != 0) // If not leader
return sMemberFacingDirections[memberId];
else if (gameData->activity == (ACTIVITY_CHAT | IN_UNION_ROOM))
return DIR_SOUTH;
else
return DIR_EAST;
}
static u32 IsUnionRoomPlayerInvisible(u32 leaderId, u32 memberId)
{
return IsVirtualObjectInvisible(UR_PLAYER_SPRITE_ID(leaderId, memberId) - UR_SPRITE_START_ID);
}
static void SpawnGroupMember(u32 leaderId, u32 memberId, u8 graphicsId, struct RfuGameData * gameData)
{
s32 x, y;
s32 id = UR_PLAYER_SPRITE_ID(leaderId, memberId);
if (IsUnionRoomPlayerInvisible(leaderId, memberId) == TRUE)
{
SetVirtualObjectInvisibility(id - UR_SPRITE_START_ID, FALSE);
SetVirtualObjectSpriteAnim(id - UR_SPRITE_START_ID, UNION_ROOM_SPAWN_IN);
}
SetVirtualObjectGraphics(id - UR_SPRITE_START_ID, graphicsId);
SetUnionRoomObjectFacingDirection(memberId, leaderId, GetNewFacingDirectionForUnionRoomPlayer(memberId, leaderId, gameData));
GetUnionRoomPlayerCoords(leaderId, memberId, &x, &y);
MapGridSetMetatileImpassabilityAt(x, y, TRUE);
}
static void DespawnGroupMember(u32 leaderId, u32 memberId)
{
s32 x, y;
SetVirtualObjectSpriteAnim(UR_PLAYER_SPRITE_ID(leaderId, memberId) - UR_SPRITE_START_ID, UNION_ROOM_SPAWN_OUT);
GetUnionRoomPlayerCoords(leaderId, memberId, &x, &y);
MapGridSetMetatileImpassabilityAt(x, y, FALSE);
}
static void AssembleGroup(u32 leaderId, struct RfuGameData * gameData)
{
s16 x, y, x2, y2;
s32 i;
PlayerGetDestCoords(&x, &y);
player_get_pos_including_state_based_drift(&x2, &y2);
if (IsVirtualObjectInvisible(UR_PLAYER_SPRITE_ID(leaderId, 0) - UR_SPRITE_START_ID) == TRUE)
{
if (IsUnionRoomPlayerAt(leaderId, 0, x, y) == TRUE || IsUnionRoomPlayerAt(leaderId, 0, x2, y2) == TRUE)
return;
SpawnGroupMember(leaderId, 0, GetUnionRoomPlayerGraphicsId(gameData->playerGender, gameData->compatibility.playerTrainerId[0]), gameData);
}
for (i = 1; i < MAX_RFU_PLAYERS; i++)
{
if (gameData->partnerInfo[i - 1] == 0)
DespawnGroupMember(leaderId, i);
else if (IsUnionRoomPlayerAt(leaderId, i, x, y) == FALSE && IsUnionRoomPlayerAt(leaderId, i, x2, y2) == FALSE)
SpawnGroupMember(leaderId, i, GetUnionRoomPlayerGraphicsId((gameData->partnerInfo[i - 1] >> PINFO_GENDER_SHIFT) & 1,
gameData->partnerInfo[i - 1] & PINFO_TID_MASK),
gameData);
}
}
static void SpawnGroupLeaderAndMembers(u32 leaderId, struct RfuGameData * gameData)
{
u32 i;
switch (gameData->activity)
{
case ACTIVITY_NONE | IN_UNION_ROOM:
case ACTIVITY_PLYRTALK | IN_UNION_ROOM:
SpawnGroupLeader(leaderId, gameData->playerGender, gameData->compatibility.playerTrainerId[0]);
for (i = 0; i < MAX_RFU_PLAYERS; i++)
DespawnGroupMember(leaderId, i);
break;
case ACTIVITY_BATTLE_SINGLE | IN_UNION_ROOM:
case ACTIVITY_TRADE | IN_UNION_ROOM:
case ACTIVITY_CHAT | IN_UNION_ROOM:
case ACTIVITY_CARD | IN_UNION_ROOM:
case ACTIVITY_ACCEPT | IN_UNION_ROOM:
case ACTIVITY_DECLINE | IN_UNION_ROOM:
case ACTIVITY_NPCTALK | IN_UNION_ROOM:
DespawnGroupLeader(leaderId);
AssembleGroup(leaderId, gameData);
break;
default:
AGB_ASSERT_EX(0, ABSPATH("rfu_union_tool.c"), 979)
}
}
static void DespawnGroupLeaderAndMembers(u32 leaderId, struct RfuGameData * gameData)
{
s32 i;
DespawnGroupLeader(leaderId);
for (i = 0; i < MAX_RFU_PLAYERS; i++)
DespawnGroupMember(leaderId, i);
}
static void UpdateUnionRoomPlayerSprites(struct WirelessLink_URoom * uroom)
{
s32 i;
struct RfuPlayer * leaders;
sUnionObjRefreshTimer = 0;
for (i = 0, leaders = uroom->playerList->players; i < MAX_UNION_ROOM_LEADERS; i++)
{
if (leaders[i].groupScheduledAnim == UNION_ROOM_SPAWN_IN)
SpawnGroupLeaderAndMembers(i, &leaders[i].rfu.data);
else if (leaders[i].groupScheduledAnim == UNION_ROOM_SPAWN_OUT)
DespawnGroupLeaderAndMembers(i, &leaders[i].rfu.data);
}
}
void ScheduleUnionRoomPlayerRefresh(struct WirelessLink_URoom *uroom)
{
sUnionObjRefreshTimer = 300;
}
void HandleUnionRoomPlayerRefresh(struct WirelessLink_URoom *uroom)
{
if (++sUnionObjRefreshTimer > 300)
UpdateUnionRoomPlayerSprites(uroom);
}
bool32 TryInteractWithUnionRoomMember(struct RfuPlayerList *list, s16 *memberIdPtr, s16 *leaderIdPtr, u8 *spriteIds)
{
s16 x, y;
s32 leaderId, memberId;
struct RfuPlayer * leaders;
if (!IsPlayerStandingStill())
return FALSE;
GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
for (leaderId = 0, leaders = list->players; leaderId < MAX_UNION_ROOM_LEADERS; leaderId++)
{
for (memberId = 0; memberId < MAX_RFU_PLAYERS; memberId++)
{
s32 objId = UR_PLAYER_SPRITE_ID(leaderId, memberId);
// Is the player in front of a group member position?
if (x != sUnionRoomPlayerCoords[leaderId][0] + sUnionRoomGroupOffsets[memberId][0] + 7)
continue;
if (y != sUnionRoomPlayerCoords[leaderId][1] + sUnionRoomGroupOffsets[memberId][1] + 7)
continue;
// Has a group member spawned at this position?
if (IsVirtualObjectInvisible(objId - UR_SPRITE_START_ID) != FALSE)
continue;
if (IsVirtualObjectAnimating(objId - UR_SPRITE_START_ID) != FALSE)
continue;
if (leaders[leaderId].groupScheduledAnim != UNION_ROOM_SPAWN_IN)
continue;
// Interaction attempt successful, face player
SetUnionRoomObjectFacingDirection(memberId, leaderId, sOppositeFacingDirection[GetPlayerFacingDirection()]);
*memberIdPtr = memberId;
*leaderIdPtr = leaderId;
return TRUE;
}
}
return FALSE;
}
static void SetUnionRoomObjectFacingDirection(s32 memberId, s32 leaderId, u8 direction)
{
TurnVirtualObject(MAX_RFU_PLAYERS * leaderId - UR_SPRITE_START_ID + memberId, direction);
}
void UpdateUnionRoomMemberFacing(u32 memberId, u32 leaderId, struct RfuPlayerList *list)
{
return SetUnionRoomObjectFacingDirection(memberId, leaderId, GetNewFacingDirectionForUnionRoomPlayer(memberId, leaderId, &list->players[leaderId].rfu.data));
}
+195 -164
View File
@@ -14,46 +14,60 @@
#include "constants/songs.h"
#include "constants/union_room.h"
struct WirelessCommunicationStatusScreenStruct
{
u32 counts[4];
u32 lastCounts[4];
u32 activities[16];
u8 taskId;
u8 rfuTaskId;
u8 filler_62[0xA];
enum {
COLOR_NONE,
COLOR_NORMAL,
COLOR_TOTAL,
COLOR_TITLE,
COLOR_UNUSED,
};
static struct WirelessCommunicationStatusScreenStruct * sWCSS;
enum {
GROUPTYPE_NONE = -1,
GROUPTYPE_TRADE,
GROUPTYPE_BATTLE,
GROUPTYPE_UNION,
GROUPTYPE_TOTAL,
NUM_GROUPTYPES
};
static struct
{
u32 groupCounts[NUM_GROUPTYPES];
u32 prevGroupCounts[NUM_GROUPTYPES];
u32 activities[NUM_TASK_DATA];
u8 taskId;
u8 rfuTaskId;
u8 filler[10];
} * sStatusScreen;
static void CB2_InitWirelessCommunicationScreen(void);
static void Task_WirelessCommunicationScreen(u8 taskId);
static void WCSS_AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 palIdx);
static bool32 UpdateCommunicationCounts(u32 * counts, u32 * lastCounts, u32 * activities, u8 taskId);
static const u16 sWCSS_Palettes[][16] = {
INCBIN_U16("graphics/misc/unk_846f4d0.gbapal"),
INCBIN_U16("graphics/misc/unk_846f4f0.gbapal"),
INCBIN_U16("graphics/misc/unk_846f510.gbapal"),
INCBIN_U16("graphics/misc/unk_846f530.gbapal"),
INCBIN_U16("graphics/misc/unk_846f550.gbapal"),
INCBIN_U16("graphics/misc/unk_846f570.gbapal"),
INCBIN_U16("graphics/misc/unk_846f590.gbapal"),
INCBIN_U16("graphics/misc/unk_846f5b0.gbapal"),
INCBIN_U16("graphics/misc/unk_846f5d0.gbapal"),
INCBIN_U16("graphics/misc/unk_846f5f0.gbapal"),
INCBIN_U16("graphics/misc/unk_846f610.gbapal"),
INCBIN_U16("graphics/misc/unk_846f630.gbapal"),
INCBIN_U16("graphics/misc/unk_846f650.gbapal"),
INCBIN_U16("graphics/misc/unk_846f670.gbapal"),
INCBIN_U16("graphics/misc/unk_846f690.gbapal"),
INCBIN_U16("graphics/misc/unk_846f6b0.gbapal")
static const u16 sPalettes[][16] = {
INCBIN_U16("graphics/wireless_status_screen/default.gbapal"),
{}, // All black. Never read
INCBIN_U16("graphics/wireless_status_screen/anim_00.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_01.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_02.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_03.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_04.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_05.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_06.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_07.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_08.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_09.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_10.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_11.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_12.gbapal"),
INCBIN_U16("graphics/wireless_status_screen/anim_13.gbapal")
};
static const u32 sBgTiles_Gfx[] = INCBIN_U32("graphics/wireless_status_screen/bg.4bpp.lz");
static const u16 sBgTiles_Tilemap[] = INCBIN_U16("graphics/wireless_status_screen/bg.bin");
static const u32 sBgTilesGfx[] = INCBIN_U32("graphics/misc/unk_846f6d0.4bpp.lz");
static const u16 sBgTilemap[] = INCBIN_U16("graphics/misc/unk_846f8e0.bin");
static const struct BgTemplate sBGTemplates[] = {
static const struct BgTemplate sBgTemplates[] = {
{
.bg = 0,
.charBaseIndex = 2,
@@ -75,29 +89,29 @@ static const struct BgTemplate sBGTemplates[] = {
static const struct WindowTemplate sWindowTemplates[] = {
{
.bg = 0x00,
.tilemapLeft = 0x03,
.tilemapTop = 0x00,
.width = 0x18,
.height = 0x03,
.paletteNum = 0x0f,
.baseBlock = 0x0001
.bg = 0,
.tilemapLeft = 3,
.tilemapTop = 0,
.width = 24,
.height = 3,
.paletteNum = 15,
.baseBlock = 0x001
}, {
.bg = 0x00,
.tilemapLeft = 0x03,
.tilemapTop = 0x04,
.width = 0x16,
.height = 0x0f,
.paletteNum = 0x0f,
.baseBlock = 0x0049
.bg = 0,
.tilemapLeft = 3,
.tilemapTop = 4,
.width = 22,
.height = 15,
.paletteNum = 15,
.baseBlock = 0x049
}, {
.bg = 0x00,
.tilemapLeft = 0x19,
.tilemapTop = 0x04,
.width = 0x02,
.height = 0x0f,
.paletteNum = 0x0f,
.baseBlock = 0x0193
.bg = 0,
.tilemapLeft = 25,
.tilemapTop = 4,
.width = 2,
.height = 15,
.paletteNum = 15,
.baseBlock = 0x193
}, DUMMY_WIN_TEMPLATE
};
@@ -109,41 +123,43 @@ static const u8 *const sPlayersTextPtrs[] = {
gText_Dynamic3Players
};
static const u8 *const sHeaderTextPtrs[] = {
gText_WirelessCommunicationStatus,
gText_PeopleTrading,
gText_PeopleBattling,
gText_PeopleInUnionRoom,
gText_PeopleCommunicating
static const u8 *const sHeaderTexts[NUM_GROUPTYPES + 1] = {
[0] = gText_WirelessCommunicationStatus,
[GROUPTYPE_TRADE + 1] = gText_PeopleTrading,
[GROUPTYPE_BATTLE + 1] = gText_PeopleBattling,
[GROUPTYPE_UNION + 1] = gText_PeopleInUnionRoom,
[GROUPTYPE_TOTAL + 1] = gText_PeopleCommunicating
};
static const u8 sCountParams[][3] = {
// activity, count idx, by
// by=0 means count all
// UB: no check for count idx == -1
{ACTIVITY_BATTLE, 1, 2},
{ACTIVITY_DBLBATTLE, 1, 2},
{ACTIVITY_MLTBATTLE, 1, 4},
{ACTIVITY_TRADE, 0, 2},
{ACTIVITY_WCARD2, 3, 2},
{ACTIVITY_WNEWS2, 3, 2},
{ACTIVITY_PJUMP, 4, 0},
{ACTIVITY_BCRUSH, 4, 0},
{ACTIVITY_BPICK, 4, 0},
{ACTIVITY_SEARCH, -1, 0},
{ACTIVITY_SPINTRADE, 0, 0},
{ACTIVITY_ITEMTRADE, -1, 0},
{0x0f, 4, 0},
{0x10, -1, 0},
{0x40, 2, 1},
{ACTIVITY_BATTLE | 0x40, 2, 2},
{ACTIVITY_TRADE | 0x40, 2, 2},
{ACTIVITY_CHAT | 0x40, 2, 0},
{ACTIVITY_CARD | 0x40, 2, 2},
{20 | 0x40, 2, 1},
{19 | 0x40, 2, 2},
{ACTIVITY_ACCEPT | 0x40, 2, 1},
{ACTIVITY_DECLINE | 0x40, 2, 1}
// Activity, group type, number of players
// 0 players means the number of players can change and should be counted dynamically
// GROUPTYPE_TOTAL have no unique group and are simply counted in the total of "people communicating".
// A handful use NUM_GROUPTYPES, which is invalid, and are changed to GROUPTYPE_TOTAL in Emerald.
// UB: GROUPTYPE_NONE (-1) can potentially be used as an index into a u8[4] in CountPlayersInGroupAndGetActivity.
static const u8 sActivityGroupInfo[][3] = {
{ACTIVITY_BATTLE_SINGLE, GROUPTYPE_BATTLE, 2},
{ACTIVITY_BATTLE_DOUBLE, GROUPTYPE_BATTLE, 2},
{ACTIVITY_BATTLE_MULTI, GROUPTYPE_BATTLE, 4},
{ACTIVITY_TRADE, GROUPTYPE_TRADE, 2},
{ACTIVITY_WONDER_CARD, GROUPTYPE_TOTAL, 2},
{ACTIVITY_WONDER_NEWS, GROUPTYPE_TOTAL, 2},
{ACTIVITY_POKEMON_JUMP, NUM_GROUPTYPES, 0},
{ACTIVITY_BERRY_CRUSH, NUM_GROUPTYPES, 0},
{ACTIVITY_BERRY_PICK, NUM_GROUPTYPES, 0},
{ACTIVITY_SEARCH, GROUPTYPE_NONE, 0},
{ACTIVITY_SPIN_TRADE, GROUPTYPE_TRADE, 0},
{ACTIVITY_ITEM_TRADE, GROUPTYPE_NONE, 0},
{ACTIVITY_RECORD_CORNER, NUM_GROUPTYPES, 0},
{ACTIVITY_BERRY_BLENDER, GROUPTYPE_NONE, 0},
{ACTIVITY_NONE | IN_UNION_ROOM, GROUPTYPE_UNION, 1},
{ACTIVITY_BATTLE_SINGLE | IN_UNION_ROOM, GROUPTYPE_UNION, 2},
{ACTIVITY_TRADE | IN_UNION_ROOM, GROUPTYPE_UNION, 2},
{ACTIVITY_CHAT | IN_UNION_ROOM, GROUPTYPE_UNION, 0},
{ACTIVITY_CARD | IN_UNION_ROOM, GROUPTYPE_UNION, 2},
{ACTIVITY_PLYRTALK | IN_UNION_ROOM, GROUPTYPE_UNION, 1},
{ACTIVITY_NPCTALK | IN_UNION_ROOM, GROUPTYPE_UNION, 2},
{ACTIVITY_ACCEPT | IN_UNION_ROOM, GROUPTYPE_UNION, 1},
{ACTIVITY_DECLINE | IN_UNION_ROOM, GROUPTYPE_UNION, 1}
};
static void CB2_RunWirelessCommunicationScreen(void)
@@ -173,14 +189,14 @@ void ShowWirelessCommunicationScreen(void)
static void CB2_InitWirelessCommunicationScreen(void)
{
SetGpuReg(REG_OFFSET_DISPCNT, 0);
sWCSS = AllocZeroed(sizeof(*sWCSS));
sStatusScreen = AllocZeroed(sizeof(*sStatusScreen));
SetVBlankCallback(NULL);
ResetBgsAndClearDma3BusyFlags(FALSE);
InitBgsFromTemplates(0, sBGTemplates, NELEMS(sBGTemplates));
SetBgTilemapBuffer(1, Alloc(0x800));
SetBgTilemapBuffer(0, Alloc(0x800));
DecompressAndLoadBgGfxUsingHeap(1, sBgTilesGfx, 0, 0, 0);
CopyToBgTilemapBuffer(1, sBgTilemap, 0, 0);
InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
SetBgTilemapBuffer(1, Alloc(BG_SCREEN_SIZE));
SetBgTilemapBuffer(0, Alloc(BG_SCREEN_SIZE));
DecompressAndLoadBgGfxUsingHeap(1, sBgTiles_Gfx, 0, 0, 0);
CopyToBgTilemapBuffer(1, sBgTiles_Tilemap, 0, 0);
InitWindows(sWindowTemplates);
DeactivateAllTextPrinters();
ResetPaletteFade();
@@ -189,14 +205,14 @@ static void CB2_InitWirelessCommunicationScreen(void)
ScanlineEffect_Stop();
m4aSoundVSyncOn();
SetVBlankCallback(VBlankCB_WirelessCommunicationScreen);
sWCSS->taskId = CreateTask(Task_WirelessCommunicationScreen, 0);
sWCSS->rfuTaskId = CreateTask_ListenToWireless();
sWCSS->lastCounts[3] = 1;
ChangeBgX(0, 0, 0);
ChangeBgY(0, 0, 0);
ChangeBgX(1, 0, 0);
ChangeBgY(1, 0, 0);
LoadPalette(sWCSS_Palettes, 0, 0x20);
sStatusScreen->taskId = CreateTask(Task_WirelessCommunicationScreen, 0);
sStatusScreen->rfuTaskId = CreateTask_ListenToWireless();
sStatusScreen->prevGroupCounts[3] = 1;
ChangeBgX(0, 0, BG_COORD_SET);
ChangeBgY(0, 0, BG_COORD_SET);
ChangeBgX(1, 0, BG_COORD_SET);
ChangeBgY(1, 0, BG_COORD_SET);
LoadPalette(sPalettes, 0, 0x20);
Menu_LoadStdPalAt(0xf0);
DynamicPlaceholderTextUtil_Reset();
FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0xF);
@@ -214,29 +230,24 @@ static void ExitWirelessCommunicationStatusScreen(void)
s32 i;
FreeAllWindowBuffers();
for (i = 0; i < 2; i++)
{
for (i = 0; i < (int)ARRAY_COUNT(sBgTemplates); i++)
Free(GetBgTilemapBuffer(i));
}
Free(sWCSS);
Free(sStatusScreen);
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
}
static void WCSS_CyclePalette(s16 * frameCtr_p, s16 * palIdx_p)
// Cycle through palettes that relocate various shades of blue to create the wave effect at the bottom of the screen.
static void CyclePalette(s16 * counter, s16 * palIdx)
{
s32 idx;
(*frameCtr_p)++;
if (*frameCtr_p > 5)
if (++(*counter) > 5)
{
(*palIdx_p)++;
if (*palIdx_p == 14)
{
*palIdx_p = 0;
}
*frameCtr_p = 0;
if (++(*palIdx) == (int)ARRAY_COUNT(sPalettes) - 2)
*palIdx = 0;
*counter = 0;
}
idx = *palIdx_p + 2;
LoadPalette(sWCSS_Palettes[idx], 0, 16);
idx = *palIdx + 2; // +2 skips over default.pal and the empty black palette after it
LoadPalette(sPalettes[idx], 0, 16);
}
static void PrintHeaderTexts(void)
@@ -247,50 +258,57 @@ static void PrintHeaderTexts(void)
FillWindowPixelBuffer(0, PIXEL_FILL(0));
FillWindowPixelBuffer(1, PIXEL_FILL(0));
FillWindowPixelBuffer(2, PIXEL_FILL(0));
width = 0xC0 - GetStringWidth(FONT_3, sHeaderTextPtrs[0], 0);
WCSS_AddTextPrinterParameterized(0, FONT_3, sHeaderTextPtrs[0], width / 2, 6, 3);
for (i = 0; i < 3; i++)
{
WCSS_AddTextPrinterParameterized(1, FONT_3, sHeaderTextPtrs[i + 1], 0, 30 * i + 10, 1);
}
WCSS_AddTextPrinterParameterized(1, FONT_3, sHeaderTextPtrs[i + 1], 0, 30 * i + 10, 2);
// Print title
width = 192 - GetStringWidth(FONT_3, sHeaderTexts[0], 0);
WCSS_AddTextPrinterParameterized(0, FONT_3, sHeaderTexts[0], width / 2, 6, COLOR_TITLE);
// Print label for each group (excluding total)
for (i = 0; i < NUM_GROUPTYPES - 1; i++)
WCSS_AddTextPrinterParameterized(1, FONT_3, sHeaderTexts[i + 1], 0, 30 * i + 10, COLOR_NORMAL);
// Print label for total
WCSS_AddTextPrinterParameterized(1, FONT_3, sHeaderTexts[i + 1], 0, 30 * i + 10, COLOR_TOTAL);
PutWindowTilemap(0);
CopyWindowToVram(0, COPYWIN_GFX);
PutWindowTilemap(1);
CopyWindowToVram(1, COPYWIN_GFX);
}
#define tState data[0]
static void Task_WirelessCommunicationScreen(u8 taskId)
{
s32 i;
switch (gTasks[taskId].data[0])
switch (gTasks[taskId].tState)
{
case 0:
PrintHeaderTexts();
gTasks[taskId].data[0]++;
gTasks[taskId].tState++;
break;
case 1:
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
ShowBg(1);
CopyBgTilemapBufferToVram(0);
ShowBg(0);
gTasks[taskId].data[0]++;
gTasks[taskId].tState++;
break;
case 2:
if (!gPaletteFade.active)
gTasks[taskId].data[0]++;
gTasks[taskId].tState++;
break;
case 3:
if (UpdateCommunicationCounts(sWCSS->counts, sWCSS->lastCounts, sWCSS->activities, sWCSS->rfuTaskId))
if (UpdateCommunicationCounts(sStatusScreen->groupCounts, sStatusScreen->prevGroupCounts, sStatusScreen->activities, sStatusScreen->rfuTaskId))
{
FillWindowPixelBuffer(2, PIXEL_FILL(0));
for (i = 0; i < 4; i++)
for (i = 0; i < NUM_GROUPTYPES; i++)
{
ConvertIntToDecimalStringN(gStringVar4, sWCSS->counts[i], STR_CONV_MODE_RIGHT_ALIGN, 2);
if (i != 3)
WCSS_AddTextPrinterParameterized(2, FONT_3, gStringVar4, 4, 30 * i + 10, 1);
ConvertIntToDecimalStringN(gStringVar4, sStatusScreen->groupCounts[i], STR_CONV_MODE_RIGHT_ALIGN, 2);
if (i != GROUPTYPE_TOTAL)
WCSS_AddTextPrinterParameterized(2, FONT_3, gStringVar4, 4, 30 * i + 10, COLOR_NORMAL);
else
WCSS_AddTextPrinterParameterized(2, FONT_3, gStringVar4, 4, 100, 2);
WCSS_AddTextPrinterParameterized(2, FONT_3, gStringVar4, 4, 100, COLOR_TOTAL);
}
PutWindowTilemap(2);
CopyWindowToVram(2, COPYWIN_FULL);
@@ -298,14 +316,14 @@ static void Task_WirelessCommunicationScreen(u8 taskId)
if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
{
PlaySE(SE_SELECT);
gTasks[sWCSS->rfuTaskId].data[15] = 0xFF;
gTasks[taskId].data[0]++;
gTasks[sStatusScreen->rfuTaskId].data[15] = 0xFF;
gTasks[taskId].tState++;
}
WCSS_CyclePalette(&gTasks[taskId].data[7], &gTasks[taskId].data[8]);
CyclePalette(&gTasks[taskId].data[7], &gTasks[taskId].data[8]);
break;
case 4:
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
gTasks[taskId].data[0]++;
gTasks[taskId].tState++;
break;
case 5:
if (!gPaletteFade.active)
@@ -317,93 +335,99 @@ static void Task_WirelessCommunicationScreen(u8 taskId)
}
}
static void WCSS_AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 palIdx)
static void WCSS_AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 * str, u8 x, u8 y, u8 mode)
{
u8 textColor[3];
switch (palIdx)
switch (mode)
{
case 0:
case COLOR_NONE: // Unused. Default to usual text colors
textColor[0] = TEXT_COLOR_TRANSPARENT;
textColor[1] = TEXT_COLOR_DARK_GRAY;
textColor[2] = TEXT_COLOR_LIGHT_GRAY;
break;
case 1:
case COLOR_NORMAL:
textColor[0] = TEXT_COLOR_TRANSPARENT;
textColor[1] = TEXT_COLOR_WHITE;
textColor[2] = TEXT_COLOR_LIGHT_GRAY;
break;
case 2:
case COLOR_TOTAL:
textColor[0] = TEXT_COLOR_TRANSPARENT;
textColor[1] = TEXT_COLOR_RED;
textColor[2] = TEXT_COLOR_LIGHT_RED;
break;
case 3:
case COLOR_TITLE:
textColor[0] = TEXT_COLOR_TRANSPARENT;
textColor[1] = TEXT_COLOR_LIGHT_GREEN;
textColor[2] = TEXT_COLOR_GREEN;
break;
case 4:
case COLOR_UNUSED:
textColor[0] = TEXT_COLOR_TRANSPARENT;
textColor[1] = TEXT_COLOR_WHITE;
textColor[2] = TEXT_COLOR_DARK_GRAY;
break;
// default: UB
}
AddTextPrinterParameterized4(windowId, fontId, x, y, fontId == FONT_0 ? 0 : 1, 0, textColor, -1, str);
AddTextPrinterParameterized4(windowId, fontId, x, y, fontId == FONT_0 ? 0 : 1, 0, textColor, TEXT_SKIP_DRAW, str);
}
static u32 CountMembersInGroup(struct UnkStruct_x20 * unk20, u32 * counts)
static u32 CountPlayersInGroupAndGetActivity(struct RfuPlayer * player, u32 * groupCounts)
{
u32 activity = unk20->gname_uname.gname.activity;
u32 activity = player->rfu.data.activity;
s32 i, j, k;
for (i = 0; i < NELEMS(sCountParams); i++)
#define group_activity(i) (sActivityGroupInfo[(i)][0])
#define group_type(i) (sActivityGroupInfo[(i)][1])
#define group_players(i) (sActivityGroupInfo[(i)][2])
for (i = 0; i < ARRAY_COUNT(sActivityGroupInfo); i++)
{
if (activity == sCountParams[i][0] && unk20->groupScheduledAnim == UNION_ROOM_SPAWN_IN)
if (activity == group_activity(i) && player->groupScheduledAnim == UNION_ROOM_SPAWN_IN)
{
if (sCountParams[i][2] == 0)
if (group_players(i) == 0)
{
k = 0;
for (j = 0; j < RFU_CHILD_MAX; j++)
{
if (unk20->gname_uname.gname.child_sprite_gender[j] != 0) k++;
}
if (player->rfu.data.partnerInfo[j] != 0) k++;
k++;
counts[sCountParams[i][1]] += k;
groupCounts[group_type(i)] += k;
}
else
{
counts[sCountParams[i][1]] += sCountParams[i][2];
groupCounts[group_type(i)] += group_players(i);
}
}
}
return activity;
#undef group_activity
#undef group_type
#undef group_players
}
static bool32 HaveCountsChanged(const u32 * newCounts, const u32 * prevCounts)
static bool32 HaveCountsChanged(const u32 * curCounts, const u32 * prevCounts)
{
s32 i;
for (i = 0; i < 4; i++)
for (i = 0; i < NUM_GROUPTYPES; i++)
{
if (newCounts[i] != prevCounts[i])
if (curCounts[i] != prevCounts[i])
return TRUE;
}
return FALSE;
}
static bool32 UpdateCommunicationCounts(u32 * counts, u32 * lastCounts, u32 * activities, u8 taskId)
static bool32 UpdateCommunicationCounts(u32 * groupCounts, u32 * prevGroupCounts, u32 * activities, u8 taskId)
{
bool32 activitiesUpdated = FALSE;
u32 buffer[4] = {0, 0, 0, 0};
struct UnkStruct_Group * group = (void *)gTasks[taskId].data;
u32 groupCountBuffer[NUM_GROUPTYPES] = {0, 0, 0, 0};
struct WirelessLink_Group * group = (void *)gTasks[taskId].data;
s32 i;
for (i = 0; i < 16; i++)
for (i = 0; i < NUM_TASK_DATA; i++)
{
u32 activity = CountMembersInGroup(&group->field_0->arr[i], buffer);
u32 activity = CountPlayersInGroupAndGetActivity(&group->playerList->players[i], groupCountBuffer);
if (activity != activities[i])
{
activities[i] = activity;
@@ -411,7 +435,7 @@ static bool32 UpdateCommunicationCounts(u32 * counts, u32 * lastCounts, u32 * ac
}
}
if (HaveCountsChanged(buffer, lastCounts) == FALSE)
if (!HaveCountsChanged(groupCountBuffer, prevGroupCounts))
{
if (activitiesUpdated == TRUE)
return TRUE;
@@ -419,8 +443,15 @@ static bool32 UpdateCommunicationCounts(u32 * counts, u32 * lastCounts, u32 * ac
return FALSE;
}
memcpy(counts, buffer, sizeof(buffer));
memcpy(lastCounts, buffer, sizeof(buffer));
counts[3] = counts[0] + counts[1] + counts[2];
memcpy(groupCounts, groupCountBuffer, sizeof(groupCountBuffer));
memcpy(prevGroupCounts, groupCountBuffer, sizeof(groupCountBuffer));
groupCounts[GROUPTYPE_TOTAL] = groupCounts[GROUPTYPE_TRADE]
+ groupCounts[GROUPTYPE_BATTLE]
+ groupCounts[GROUPTYPE_UNION]
#ifdef BUGFIX
+ groupCounts[GROUPTYPE_TOTAL] // Missing count for activities not in above groups
#endif
;
return TRUE;
}