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
+3 -3
View File
@@ -1,3 +1,3 @@
gHostRFUtgtGnameBuffer
Rfu
gHostRFUtgtUnameBuffer
gHostRfuGameData
gRfu
gHostRfuUsername
+1 -10
View File
@@ -1,12 +1,3 @@
.set LOCALID_UNION_ROOM_PLAYER_4, 2
.set LOCALID_UNION_ROOM_PLAYER_8, 3
.set LOCALID_UNION_ROOM_PLAYER_7, 4
.set LOCALID_UNION_ROOM_PLAYER_6, 5
.set LOCALID_UNION_ROOM_PLAYER_5, 6
.set LOCALID_UNION_ROOM_PLAYER_3, 7
.set LOCALID_UNION_ROOM_PLAYER_2, 8
.set LOCALID_UNION_ROOM_PLAYER_1, 9
UnionRoom_MapScripts::
map_script MAP_SCRIPT_ON_RESUME, UnionRoom_OnResume
map_script MAP_SCRIPT_ON_TRANSITION, UnionRoom_OnTransition
@@ -29,7 +20,7 @@ UnionRoom_OnResume::
removeobject LOCALID_UNION_ROOM_PLAYER_6
removeobject LOCALID_UNION_ROOM_PLAYER_7
removeobject LOCALID_UNION_ROOM_PLAYER_8
special UnionRoomSpecial
special RunUnionRoom
end
UnionRoom_OnTransition::
+1 -1
View File
@@ -796,7 +796,7 @@ CableClub_EventScript_EnterUnionRoom::
special SetCableClubWarp
warpspinenter MAP_UNION_ROOM, 7, 11
waitstate
special UnionRoomSpecial
special RunUnionRoom
waitstate
end
+1 -1
View File
@@ -373,7 +373,7 @@ gSpecials::
def_special IsWirelessAdapterConnected
def_special TryBecomeLinkLeader
def_special TryJoinLinkGroup
def_special UnionRoomSpecial
def_special RunUnionRoom
def_special ShowWirelessCommunicationScreen
def_special EnableNationalPokedex
def_special SetWalkingIntoSignVars

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 308 B

-19
View File
@@ -1,19 +0,0 @@
JASC-PAL
0100
16
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 490 B

+14 -3
View File
@@ -189,10 +189,21 @@
#define TRACKS_FOOT 1
#define TRACKS_BIKE_TIRE 2
#define OBJ_EVENT_ID_PLAYER 0xFF
#define OBJ_EVENT_ID_CAMERA 0x7F
#define OBJ_KIND_NORMAL 0
#define OBJ_KIND_CLONE 255
// Special object event local ids
#define OBJ_EVENT_ID_PLAYER 0xFF
#define OBJ_EVENT_ID_CAMERA 0x7F
// Object event local ids referenced in C files
#define LOCALID_UNION_ROOM_PLAYER_4 2
#define LOCALID_UNION_ROOM_PLAYER_8 3
#define LOCALID_UNION_ROOM_PLAYER_7 4
#define LOCALID_UNION_ROOM_PLAYER_6 5
#define LOCALID_UNION_ROOM_PLAYER_5 6
#define LOCALID_UNION_ROOM_PLAYER_3 7
#define LOCALID_UNION_ROOM_PLAYER_2 8
#define LOCALID_UNION_ROOM_PLAYER_1 9
#endif // GUARD_CONSTANTS_EVENT_OBJECTS_H
+59 -34
View File
@@ -1,47 +1,51 @@
#ifndef GUARD_CONSTANTS_UNION_ROOM_H
#define GUARD_CONSTANTS_UNION_ROOM_H
// The number of possible group leaders visible in the Union Room.
// Note that this is different than the number of people actively
// connected as children via the Wireless Adapter, which cannot
// exceed RFU_CHILD_MAX (4), for a total of 5 including the player.
#define MAX_UNION_ROOM_LEADERS 8
#define UNION_ROOM_SPAWN_NONE 0
#define UNION_ROOM_SPAWN_IN 1
#define UNION_ROOM_SPAWN_OUT 2
#define ACTIVITY_NONE 0
#define ACTIVITY_BATTLE 1
#define ACTIVITY_DBLBATTLE 2
#define ACTIVITY_MLTBATTLE 3
#define ACTIVITY_TRADE 4
#define ACTIVITY_CHAT 5
#define ACTIVITY_WCARD 6
#define ACTIVITY_WNEWS 7
#define ACTIVITY_CARD 8
#define ACTIVITY_PJUMP 9
#define ACTIVITY_BCRUSH 10
#define ACTIVITY_BPICK 11
#define ACTIVITY_SEARCH 12
#define ACTIVITY_SPINTRADE 13
#define ACTIVITY_ITEMTRADE 14
#define UNION_ROOM_MAX_LEVEL 30
// The number of possible trainer classes for a trainer of a given gender in the Union Room.
// This value is necessarily a power of 2 because of the way it's treated in GetUnionRoomTrainerPic / GetUnionRoomTrainerClass
#define NUM_UNION_ROOM_CLASSES (1 << 3) // 8
#define ACTIVITY_NONE 0
#define ACTIVITY_BATTLE_SINGLE 1
#define ACTIVITY_BATTLE_DOUBLE 2
#define ACTIVITY_BATTLE_MULTI 3
#define ACTIVITY_TRADE 4
#define ACTIVITY_CHAT 5
#define ACTIVITY_WONDER_CARD_DUP 6 // Duplicates of later WONDER constants
#define ACTIVITY_WONDER_NEWS_DUP 7 //
#define ACTIVITY_CARD 8
#define ACTIVITY_POKEMON_JUMP 9
#define ACTIVITY_BERRY_CRUSH 10
#define ACTIVITY_BERRY_PICK 11
#define ACTIVITY_SEARCH 12
#define ACTIVITY_SPIN_TRADE 13
#define ACTIVITY_ITEM_TRADE 14 // Replaced with ACTIVITY_BATTLE_TOWER_OPEN in Emerald
#define ACTIVITY_RECORD_CORNER 15
#define ACTIVITY_BERRY_BLENDER 16
// Player response
#define ACTIVITY_ACCEPT 17
#define ACTIVITY_DECLINE 18
#define ACTIVITY_ACCEPT 17
#define ACTIVITY_DECLINE 18
#define ACTIVITY_NPCTALK 19
#define ACTIVITY_PLYRTALK 20
#define ACTIVITY_NPCTALK 19
#define ACTIVITY_PLYRTALK 20
// Duplicate IDs?
#define ACTIVITY_WCARD2 21
#define ACTIVITY_WNEWS2 22
#define ACTIVITY_WONDER_CARD 21
#define ACTIVITY_WONDER_NEWS 22
#define IN_UNION_ROOM 0x40
// Used in UR_AddTextPrinterParameterized
#define UR_COLOR_DKE_WHT_LTE 0
#define UR_COLOR_RED_WHT_LTR 1
#define UR_COLOR_GRN_WHT_LTG 2
#define UR_COLOR_WHT_WHT_LTE 3
#define UR_COLOR_WHT_DKE_LTE 4
#define UR_COLOR_GRN_DN6_LTB 5
#define UR_COLOR_DN5_DN6_LTB 6
#define IN_UNION_ROOM (1 << 6)
#define LINK_GROUP_SINGLE_BATTLE 0
#define LINK_GROUP_DOUBLE_BATTLE 1
@@ -52,9 +56,30 @@
#define LINK_GROUP_BERRY_PICKING 6
#define LINK_GROUP_WONDER_CARD 7
#define LINK_GROUP_WONDER_NEWS 8
#define NUM_LINK_GROUP_TYPES 9
#define LINK_GROUP_UNION_ROOM_RESUME 9
#define LINK_GROUP_UNION_ROOM_INIT 10
#define LINK_GROUP_UNK_11 11
#define LINK_GROUP_UNK_12 12
#define NUM_LINK_GROUP_TYPES 13
#define UR_TRADE_MATCH 0
#define UR_TRADE_NOTYPE 1
#define UR_TRADE_NOEGG 2
#define UR_TRADE_READY 0
#define UR_TRADE_PLAYER_NOT_READY 1
#define UR_TRADE_PARTNER_NOT_READY 2
#define UR_INTERACT_PLAYER_1 1
#define UR_INTERACT_PLAYER_2 2
#define UR_INTERACT_PLAYER_3 3
#define UR_INTERACT_PLAYER_4 4
#define UR_INTERACT_PLAYER_5 5
#define UR_INTERACT_PLAYER_6 6
#define UR_INTERACT_PLAYER_7 7
#define UR_INTERACT_PLAYER_8 8
#define UR_INTERACT_ATTENDANT 9
#define UR_INTERACT_UNUSED 10
#define UR_INTERACT_START_MENU 11
#endif //GUARD_CONSTANTS_UNION_ROOM_H
+3
View File
@@ -27,6 +27,9 @@ typedef double f64;
typedef u8 bool8;
typedef u16 bool16;
typedef u32 bool32;
typedef vu8 vbool8;
typedef vu16 vbool16;
typedef vu32 vbool32;
struct BgCnt
{
+1 -2
View File
@@ -269,7 +269,7 @@ void SetSuppressLinkErrorMessage(bool8);
bool8 HasLinkErrorOccurred(void);
void ResetSerial(void);
u32 LinkMain1(u8 *, u16 *, u16[MAX_RFU_PLAYERS][CMD_LENGTH]);
void RFUVSync(void);
void RfuVSync(void);
void Timer3Intr(void);
void SerialCB(void);
u8 GetLinkPlayerCount(void);
@@ -277,7 +277,6 @@ bool32 InUnionRoom(void);
void SetLinkStandbyCallback(void);
void SetWirelessCommType1(void);
void LinkRfu_DestroyIdleTask(void);
void SetCloseLinkCallback(void);
void OpenLink(void);
bool8 IsLinkMaster(void);
+162 -140
View File
@@ -6,35 +6,29 @@
#include "link.h"
#include "AgbRfu_LinkManager.h"
#define RFUCMD_MASK 0xFF00
#define RFUCMD_MASK 0xFF00
#define RFUCMD_SEND_PACKET 0x2F00
#define RFUCMD_READY_CLOSE_LINK 0x5f00
#define RFUCMD_READY_EXIT_STANDBY 0x6600
#define RFUCMD_PLAYERS_LIST 0x7700
#define RFUCMD_PLAYERS_LIST_2 0x7800
#define RFUCMD_SEND_BLOCK_INIT 0x8800
#define RFUCMD_SEND_BLOCK_STEP 0x8900
#define RFUCMD_SEND_BLOCK_REQ 0xa100
#define RFUCMD_SEND_HELD_KEYS 0xbe00
#define RFUCMD_PARENT_DISCONNECT 0xed00
#define RFUCMD_CHILD_DISCONNECT 0xee00
#define RFUCMD_SEND_PACKET 0x2F00
#define RFUCMD_BLENDER_SEND_KEYS 0x4400
#define RFUCMD_READY_CLOSE_LINK 0x5F00
#define RFUCMD_READY_EXIT_STANDBY 0x6600
#define RFUCMD_SEND_PLAYER_IDS 0x7700
#define RFUCMD_SEND_PLAYER_IDS_NEW 0x7800
#define RFUCMD_SEND_BLOCK_INIT 0x8800
#define RFUCMD_SEND_BLOCK 0x8900
#define RFUCMD_SEND_BLOCK_REQ 0xA100
#define RFUCMD_SEND_HELD_KEYS 0xBE00
#define RFUCMD_DISCONNECT 0xED00
#define RFUCMD_DISCONNECT_PARENT 0xEE00
#define RFU_PACKET_SIZE 6
#define RFU_SERIAL_7F7D 0x7F7D
#define RFU_SERIAL_GAME 0x0002 // Serial number for Pokémon game (FRLG or Emerald)
#define RFU_SERIAL_WONDER_DISTRIBUTOR 0x7F7D // Serial number for distributing Wonder Cards / News
#define RFU_SERIAL_END 0xFFFF
#define COMM_SLOT_LENGTH 14
#define RECV_QUEUE_NUM_SLOTS 20
#define RECV_QUEUE_SLOT_LENGTH (14 * MAX_RFU_PLAYERS)
#define SEND_QUEUE_NUM_SLOTS 40
#define SEND_QUEUE_SLOT_LENGTH 14
#define BACKUP_QUEUE_NUM_SLOTS 2
#define BACKUP_QUEUE_SLOT_LENGTH 14
#define UNUSED_QUEUE_NUM_SLOTS 2
#define UNUSED_QUEUE_SLOT_LENGTH 256
#define RFU_PACKET_SIZE 6
@@ -48,50 +42,88 @@
#define RFU_STATUS_WAIT_ACK_JOIN_GROUP 7
#define RFU_STATUS_LEAVE_GROUP_NOTICE 8
#define RFU_STATUS_LEAVE_GROUP 9
#define RFU_STATUS_10 10
#define RFU_STATUS_11 11
#define RFU_STATUS_CHILD_LEAVE_READY 10
#define RFU_STATUS_CHILD_LEAVE 11
#define RFU_STATUS_ACK_JOIN_GROUP 12
#define RFU_RECV_IDLE 0
#define RFU_RECV_RECEIVING 1
#define RFU_RECV_FINISHED 2
// Values for disconnectMode
enum {
RFU_DISCONNECT_NONE,
RFU_DISCONNECT_ERROR,
RFU_DISCONNECT_NORMAL,
};
// Values for errorState
enum {
RFU_ERROR_STATE_NONE,
RFU_ERROR_STATE_OCCURRED,
RFU_ERROR_STATE_PROCESSED,
RFU_ERROR_STATE_DISCONNECTING,
RFU_ERROR_STATE_IGNORE,
};
// These error flags are set in errorInfo, and given as
// the uppermost 16 bits of 'status' for sLinkErrorBuffer.
// The first 8 bits are reserved for the link manager msg
// when the error occurred, and the last 8 bits are this
// sequence of presumably meaningful error flags, but
// ultimately sLinkErrorBuffer's status is never read.
#define F_RFU_ERROR_1 (1 << 8)
#define F_RFU_ERROR_2 (1 << 9) // Never set
#define F_RFU_ERROR_3 (1 << 10) // Never set
#define F_RFU_ERROR_4 (1 << 11) // Never set
#define F_RFU_ERROR_5 (1 << 12)
#define F_RFU_ERROR_6 (1 << 13)
#define F_RFU_ERROR_7 (1 << 14)
#define F_RFU_ERROR_8 (1 << 15)
// RfuTgtData.gname is read as these structs.
struct GFtgtGnameSub
struct RfuGameCompatibilityData
{
u16 language:4;
u16 hasNews:1;
u16 hasCard:1;
u16 unknown:1;
u16 unknown:1; // Never read
u16 isChampion:1;
u16 hasNationalDex:1;
u16 gameClear:1;
u16 version:4;
u16 unk_01_6:2;
u16 unused:2;
u8 playerTrainerId[2];
};
struct __attribute__((packed, aligned(2))) GFtgtGname
// This struct is sent via the Wireless Adapter as the game name or "gname" data.
// Gname is only applicable during Wireless Single Game Pak Multiplay, when the
// adapter needs this data for connection. Per the RFU manual, during "normal"
// wireless play (the kind the Pokémon games use) the gname data can be used for
// anything the developers want. This struct is what GF decided to use it for.
// It can be up to 13 bytes in size (RFU_GAME_NAME_LENGTH).
// The player's name is sent separately as the username ("uname"), and does not
// use a struct (gHostRfuUsername).
struct __attribute__((packed, aligned(2))) RfuGameData
{
struct GFtgtGnameSub unk_00;
u8 child_sprite_gender[RFU_CHILD_MAX]; // u8 sprite_idx:3;
// u8 gender:1;
// u8 unk_4:3
// u8 active:1
u16 species:10;
u16 type:6;
struct RfuGameCompatibilityData compatibility;
u8 partnerInfo[RFU_CHILD_MAX];
u16 tradeSpecies:10;
u16 tradeType:6;
u8 activity:7;
u8 started:1;
u8 startedActivity:1;
u8 playerGender:1;
u8 level:7;
u8 tradeLevel:7;
u8 padding;
}; // size: RFU_GNAME_SIZE
struct Padded_U8
{
u8 value;
};
// Constants for getting/setting information in 'partnerInfo' of RfuGameData.
// This data is used to determine what the link partners look like from
// the host's perspective.
// Bits 0-2 are a shortened trainerId
// Bit 3 is the player's gender
// Bits 4-6 are unknown/unused
// Bit 7 is an 'active' flag
#define PINFO_TID_MASK 0x7
#define PINFO_GENDER_SHIFT 3
#define PINFO_ACTIVE_FLAG (1 << 7)
struct RfuBlockSend
{
/* 0x00 */ u16 next;
@@ -106,59 +138,50 @@ struct RfuBlockSend
struct RfuRecvQueue
{
/* 0x000 */ u8 slots[RECV_QUEUE_NUM_SLOTS][RECV_QUEUE_SLOT_LENGTH];
/* 0x578 */ vu8 recv_slot;
/* 0x579 */ vu8 send_slot;
/* 0x000 */ u8 slots[RECV_QUEUE_NUM_SLOTS][COMM_SLOT_LENGTH * MAX_RFU_PLAYERS];
/* 0x578 */ vu8 recvSlot;
/* 0x579 */ vu8 sendSlot;
/* 0x57a */ vu8 count;
/* 0x57b */ vu8 full;
};
struct RfuSendQueue
{
/* 0x000 */ u8 slots[SEND_QUEUE_NUM_SLOTS][SEND_QUEUE_SLOT_LENGTH];
/* 0x230 */ vu8 recv_slot;
/* 0x231 */ vu8 send_slot;
/* 0x000 */ u8 slots[SEND_QUEUE_NUM_SLOTS][COMM_SLOT_LENGTH];
/* 0x230 */ vu8 recvSlot;
/* 0x231 */ vu8 sendSlot;
/* 0x232 */ vu8 count;
/* 0x233 */ vu8 full;
};
struct RfuBackupQueue
{
/* 0x00 */ u8 slots[BACKUP_QUEUE_NUM_SLOTS][BACKUP_QUEUE_SLOT_LENGTH];
/* 0x1c */ vu8 recv_slot;
/* 0x1d */ vu8 send_slot;
/* 0x00 */ u8 slots[BACKUP_QUEUE_NUM_SLOTS][COMM_SLOT_LENGTH];
/* 0x1c */ vu8 recvSlot;
/* 0x1d */ vu8 sendSlot;
/* 0x1e */ vu8 count;
};
struct RfuUnusedQueue
struct RfuManager
{
/* 0x000 */ u8 slots[UNUSED_QUEUE_NUM_SLOTS][UNUSED_QUEUE_SLOT_LENGTH];
/* 0x200 */ vu8 recv_slot;
/* 0x201 */ vu8 send_slot;
/* 0x202 */ vu8 count;
/* 0x203 */ vu8 full;
};
typedef struct UnkRfuStruct_2
{
/* 0x000 */ void (*RfuFunc)(void);
/* 0x000 */ void (*callback)(void);
/* 0x004 */ u16 state;
/* 0x006 */ u8 filler_06[4];
/* 0x00a */ u16 linkman_msg;
/* 0x00c */ u8 parent_child;
/* 0x006 */ u8 unused1[4];
/* 0x00a */ u16 errorInfo;
/* 0x00c */ u8 parentChild;
/* 0x00d */ u8 playerCount;
/* 0x00e */ u8 unk_0e;
/* 0x00f */ u8 unk_0f;
/* 0x010 */ u16 linkman_param[2];
/* 0x014 */ u8 main_UNI_recvBuffer[RFU_CHILD_MAX][14];
/* 0x04c */ u8 lastCmdBeforeCommInterrupt[14];
/* 0x05a */ u8 cmdA100_blockRequestType;
/* 0x00e */ bool8 runParentMain2;
/* 0x00f */ u8 unused2;
/* 0x010 */ u16 errorParams[2];
/* 0x014 */ u8 childRecvBuffer[RFU_CHILD_MAX][COMM_SLOT_LENGTH];
/* 0x04c */ u8 childSendBuffer[COMM_SLOT_LENGTH];
/* 0x05a */ u8 blockRequestType;
/* 0x05b */ u8 sendBlockInitDelay;
/* 0x05c */ bool8 blockReceived[MAX_RFU_PLAYERS];
/* 0x061 */ u8 numBlocksReceived[MAX_RFU_PLAYERS];
/* 0x066 */ u8 idleTaskId;
/* 0x067 */ u8 searchTaskId;
/* 0x068 */ u8 filler_68[4];
/* 0x068 */ u8 unused3[4];
/* 0x06c */ struct RfuBlockSend sendBlock;
/* 0x080 */ struct RfuBlockSend recvBlock[MAX_RFU_PLAYERS];
/* 0x0e4 */ bool8 readyCloseLink[MAX_RFU_PLAYERS];
@@ -170,67 +193,66 @@ typedef struct UnkRfuStruct_2
/* 0x0f2 */ u16 packet[RFU_PACKET_SIZE];
/* 0x0fe */ u16 resendExitStandbyTimer;
/* 0x100 */ u16 resendExitStandbyCount;
/* 0x102 */ u8 unk_102;
/* 0x104 */ struct RfuTgtData tgtData;
/* 0x102 */ u8 childSendCmdId;
/* 0x104 */ struct RfuTgtData parent;
/* 0x124 */ struct RfuRecvQueue recvQueue;
/* 0x6a0 */ struct RfuSendQueue sendQueue;
/* 0x8d4 */ struct RfuBackupQueue backupQueue;
/* 0x8f4 */ vu8 linkRecovered;
/* 0x8f5 */ u8 reconnectedParentIdx;
/* 0x8f6 */ vu8 child_slot;
/* 0x8f7 */ u8 unk_c3f[70];
/* 0x8f5 */ u8 reconnectParentId;
/* 0x8f6 */ vu8 childSlot;
/* 0x8f7 */ u8 childRecvQueue[COMM_SLOT_LENGTH * MAX_RFU_PLAYERS];
/* 0x93d */ u8 sendStatus;
/* 0x93e */ u8 recvStatus;
/* 0x93f */ u8 recvCmds[MAX_RFU_PLAYERS][7][2];
/* 0x93f */ u8 recvCmds[MAX_RFU_PLAYERS][CMD_LENGTH - 1][2];
/* 0x985 */ u8 parentId;
/* 0x986 */ u8 multiplayerId; // childId
/* 0x987 */ u8 unk_ccf;
/* 0x988 */ vu8 sem_UNI_SendRecv;
/* 0x987 */ u8 connectParentFailures;
/* 0x988 */ vu8 childSendCount;
/* 0x989 */ u8 partnerSendStatuses[RFU_CHILD_MAX];
/* 0x98d */ u8 partnerRecvStatuses[RFU_CHILD_MAX];
/* 0x991 */ u8 linkClosing;
/* 0x992 */ u8 unk_cda;
/* 0x993 */ volatile bool8 unk_cdb;
/* 0x994 */ volatile bool8 unk_cdc;
/* 0x995 */ u8 unk_cdd;
/* 0x991 */ bool8 stopNewConnections;
/* 0x992 */ u8 parentSendSlot;
/* 0x993 */ vbool8 parentFinished;
/* 0x994 */ vbool8 parentMain2Failed;
/* 0x995 */ u8 unused5;
/* 0x996 */ u8 linkPlayerIdx[RFU_CHILD_MAX];
/* 0x99a */ u8 bm_PartnerFlags;
/* 0x99b */ u8 bm_DisconnectSlot;
/* 0x99c */ u8 unk_ce4;
/* 0x99d */ u8 bmChatLeaderMaybe;
/* 0x99e */ u8 unionRoomChatters;
/* 0x99a */ u8 parentSlots;
/* 0x99b */ u8 disconnectSlots;
/* 0x99c */ u8 disconnectMode;
/* 0x99d */ u8 nextChildBits;
/* 0x99e */ u8 newChildQueue;
/* 0x99f */ u8 acceptSlot_flag;
/* 0x9a0 */ bool8 foundNewLeaderMaybe;
/* 0x9a1 */ u8 unk_ce9;
/* 0x9a2 */ u8 unk_cea[RFU_CHILD_MAX];
/* 0x9a6 */ u8 unk_cee[RFU_CHILD_MAX];
} GF_RFU_MANAGER; // size: 0x9AC
/* 0x9a0 */ bool8 playerExchangeActive;
/* 0x9a1 */ u8 incomingChild;
/* 0x9a2 */ u8 numChildRecvErrors[RFU_CHILD_MAX];
/* 0x9a6 */ u8 childRecvIds[RFU_CHILD_MAX];
}; // size: 0x9AC
extern struct GFtgtGname gHostRFUtgtGnameBuffer;
extern u8 gHostRFUtgtUnameBuffer[];
extern GF_RFU_MANAGER Rfu;
extern struct RfuGameData gHostRfuGameData;
extern u8 gHostRfuUsername[];
extern struct RfuManager gRfu;
// GameFreak signatures
void AddTextPrinterToWindow1(const u8 *str);
bool32 MG_PrintTextOnWindow1AndWaitButton(u8 * cmdPtr, const u8 * src);
bool32 PrintMysteryGiftMenuMessage(u8 * cmdPtr, const u8 * src);
void LinkRfu_FatalError(void);
void MG_DrawCheckerboardPattern(void);
void Rfu_SetCloseLinkCallback(void);
bool8 IsLinkRfuTaskFinished(void);
void DestroyWirelessStatusIndicatorSprite(void);
void MEvent_CreateTask_CardOrNewsWithFriend(u32 arg0);
void MEvent_CreateTask_CardOrNewsOverWireless(u32 arg0);
void MEvent_CreateTask_Leader(u32 arg0);
void CreateTask_LinkMysteryGiftWithFriend(u32 activity);
void CreateTask_LinkMysteryGiftOverWireless(u32 activity);
void CreateTask_SendMysteryGift(u32 activity);
void Rfu_SendPacket(void *data);
u8 CreateTask_ListenToWireless(void);
void LinkRfu_DestroyIdleTask(void);
void DestroyTask_RfuIdle(void);
void InitRFUAPI(void);
void sub_80FB128(bool32 a0);
void RfuSetIgnoreError(bool32 enable);
bool32 IsSendingKeysToRfu(void);
void ClearLinkRfuCallback(void);
u8 GetRfuPlayerCount(void);
u8 Rfu_GetLinkPlayerCount(void);
void StartSendingKeysToRfu(void);
u8 LinkRfu_GetMultiplayerId(void);
u8 Rfu_GetMultiplayerId(void);
bool32 Rfu_InitBlockSend(const u8 * src, size_t size);
bool8 Rfu_SendBlockRequest(u8 blockRequestType);
u8 Rfu_GetBlockReceivedStatus(void);
@@ -238,15 +260,15 @@ void Rfu_SetBlockReceivedFlag(u8 linkPlayerId);
void Rfu_ResetBlockReceivedFlag(u8 linkPlayerId);
bool8 Rfu_IsMaster(void);
void ResetLinkRfuGFLayer(void);
bool32 LinkRfuMain1(void);
bool32 LinkRfuMain2(void);
bool32 RfuMain1(void);
bool32 RfuMain2(void);
bool32 IsRfuRecvQueueEmpty(void);
u32 GetRfuRecvQueueLength(void);
void LinkRfu_Shutdown(void);
void LinkRfu_CreateIdleTask(void);
bool8 ToggleLMANlinkRecovery(bool32 enable);
void var_800D_set_xB(void);
struct GFtgtGname *GetHostRFUtgtGname(void);
void CreateTask_RfuIdle(void);
bool8 Rfu_SetLinkRecovery(bool32 enable);
void SetUsingUnionRoomStartMenu(void);
struct RfuGameData *GetHostRfuGameData(void);
void UpdateWirelessStatusIndicatorSprite(void);
void InitRFU(void);
bool32 RfuHasErrored(void);
@@ -262,44 +284,44 @@ bool8 RfuBackupQueue_Dequeue(struct RfuBackupQueue *queue, u8 *dest);
void RfuBackupQueue_Enqueue(struct RfuBackupQueue *queue, const u8 *dest);
bool8 RfuRecvQueue_Dequeue(struct RfuRecvQueue * queue, u8 *dest);
void RfuSendQueue_Enqueue(struct RfuSendQueue * queue, u8 *src);
void InitHostRFUtgtGname(struct GFtgtGname *data, u8 activity, bool32 started, s32 child_sprite_genders);
void InitHostRfuGameData(struct RfuGameData *data, u8 activity, bool32 started, s32 partnerInfo);
void UpdateGameData_GroupLockedIn(bool8 started);
bool32 IsRfuSerialNumberValid(u32 serialNo);
bool8 IsRfuRecoveringFromLinkLoss(void);
bool8 LmanAcceptSlotFlagIsNotZero(void);
void LinkRfu_StopManagerAndFinalizeSlots(void);
bool32 sub_80FA5D4(void);
bool32 sub_80FC1CC(void);
bool32 WaitRfuState(bool32 a0);
bool32 CheckTrainerHasLeftByIdAndName(u16 trainerId, const u8 *trainerName);
void SendByteToPartnerByIdAndName(u8 a0, u16 a1, const u8 *a2);
u32 WaitSendByteToPartnerByIdAndName(u16 a0, const u8 *a1);
void SetHostRFUtgtGname(u8 activity, u32 child_sprite_genders, u32 a2);
bool32 RfuTryDisconnectLeavingChildren(void);
bool32 IsRfuCommunicatingWithAllChildren(void);
bool32 WaitRfuState(bool32 force);
bool32 HasTrainerLeftPartnersList(u16 trainerId, const u8 *trainerName);
void SendRfuStatusToPartner(u8 status, u16 trainerId, const u8 *name);
u32 WaitSendRfuStatusToPartner(u16 trainerId, const u8 *name);
void SetHostRfuGameData(u8 activity, u32 partnerInfo, bool32 startedActivity);
void InitializeRfuLinkManager_LinkLeader(u32 availSlots);
void RequestDisconnectSlotByTrainerNameAndId(const u8 *trainerName, u16 trainerId);
void LinkRfu3_SetGnameUnameFromStaticBuffers(struct GFtgtGname *gname, u8 *uname);
void CopyHostRfuGameDataAndUsername(struct RfuGameData *gameData, u8 *username);
void InitializeRfuLinkManager_JoinGroup(void);
void SendLeaveGroupNotice(void);
void CreateTask_RfuReconnectWithParent(const u8 *src, u16 trainerId);
void UpdateGameDataWithActivitySpriteGendersFlag(u8 activity, u32 child_sprite_genders, u32 started);
void RecordMixTrainerNames(void);
void UpdateGameData_SetActivity(u8 activity, u32 partnerInfo, u32 startedActivity);
void SaveLinkTrainerNames(void);
void LinkRfu_CreateConnectionAsParent();
void LinkRfu_StopManagerBeforeEnteringChat();
void SetGnameBufferWonderFlags(bool32 hasNews, bool32 hasCard);
void ClearAndInitHostRFUtgtGname(void);
void sub_80F8FA0(void);
void RfuUpdatePlayerGnameStateAndSend(u32 type, u32 species, u32 level);
void SetHostRfuWonderFlags(bool32 hasNews, bool32 hasCard);
void ResetHostRfuGameData(void);
void StopUnionRoomLinkManager(void);
void SetTradeBoardRegisteredMonInfo(u32 type, u32 species, u32 level);
bool32 IsUnionRoomListenTaskActive(void);
void InitializeRfuLinkManager_EnterUnionRoom(void);
void sub_80FBD6C(u32 a0);
void sub_80FC114(const u8 *name, struct GFtgtGname *structPtr, u8 a2);
void Rfu_DisconnectPlayerById(u32 playerIdx);
void TryConnectToUnionRoomParent(const u8 *name, struct RfuGameData *parent, u8 activity);
bool32 PlayerHasMetTrainerBefore(u16 id, u8 *name);
bool8 LinkRfu_GetNameIfCompatible(struct GFtgtGname *gname, u8 *uname, u8 idx);
bool8 LinkRfu_GetNameIfSerial7F7D(struct GFtgtGname *gname, u8 *uname, u8 idx);
bool32 RfuHasFoundNewLeader(void);
void Rfu_UnionRoomChat_StopLinkManager(void);
void sub_80FB9D0(void);
void sub_80FB030(u32 a0);
bool8 Rfu_GetCompatiblePlayerData(struct RfuGameData *gameData, u8 *username, u8 idx);
bool8 Rfu_GetWonderDistributorPlayerData(struct RfuGameData *gameData, u8 *username, u8 idx);
bool32 Rfu_IsPlayerExchangeActive(void);
void Rfu_StopPartnerSearch(void);
void RfuSetNormalDisconnectMode(void);
void SetUnionRoomChatPlayerData(u32 numPlayers);
void ClearRecvCommands(void);
#include "mevent_server.h"
+2 -2
View File
@@ -101,8 +101,8 @@ void InitMEventData(void);
u16 MEvent_GetBattleCardCount(u32 command);
void MysteryGift_TryIncrementStat(u32 eventId, u32 trainerId);
u16 *GetMEventProfileECWordsMaybe(void);
void ResetReceivedWonderCardFlag(void);
bool32 MEventHandleReceivedWonderCard(u16 flagId);
void MysteryGift_DisableStats(void);
bool32 MysteryGift_TryEnableStatsByFlagId(u16 flagId);
u16 GetWonderCardFlagId(void);
#endif //GUARD_MEVENT_H
+2 -2
View File
@@ -6,8 +6,8 @@ extern bool8 gGiftIsFromEReader;
void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void);
void PrintMysteryGiftOrEReaderTopMenu(bool8, bool32);
void c2_mystery_gift(void);
void c2_mystery_gift_e_reader_run(void);
s8 mevent_message_print_and_prompt_yes_no(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str);
void CB2_MysteryGiftEReader(void);
s8 DoMysteryGiftYesNo(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str);
void MG_DrawTextBorder(u8 windowId);
u16 GetMysteryGiftBaseBlock(void);
-16
View File
@@ -1,16 +0,0 @@
#ifndef GUARD_UNION_ROOM_PLAYER_AVATAR_H
#define GUARD_UNION_ROOM_PLAYER_AVATAR_H
#include "union_room.h"
u8 ZeroUnionObjWork(struct UnionObj * ptr);
void DeleteUnionObjWorkAndStopTask(void);
void CreateGroupMemberObjectsInvisible(u8 *spriteIds, s32 group);
void DestroyGroupMemberObjects(u8 *spriteIds);
void MakeGroupAssemblyAreasPassable(void);
void ScheduleUnionRoomPlayerRefresh(struct UnkStruct_URoom *uroom_p);
void HandleUnionRoomPlayerRefresh(struct UnkStruct_URoom *uroom_p);
bool32 RfuUnionTool_GetGroupAndMemberInFrontOfPlayer(struct UnkStruct_Main0 *main0_p, s16 *member_p, s16 *group_p, u8 *spriteIds);
void UpdateUnionGroupMemberFacing(u32 member, u32 group, struct UnkStruct_Main0 *main0_p);
#endif //GUARD_UNION_ROOM_PLAYER_AVATAR_H
+3 -3
View File
@@ -13,10 +13,10 @@ extern const u8 gText_FemaleSymbol4[];
extern const u8 gText_GenderlessSymbol[];
extern const u16 gTradeOrHatchMonShadowTilemap[];
void CB2_ReturnFromLinkTrade(void);
void CB2_StartCreateTradeMenu(void);
s32 Trade_CalcLinkPlayerCompatibilityParam(void);
s32 CanRegisterMonForTradingBoard(struct GFtgtGnameSub rfuPlayer, u16 species2, u16 species, u8 isEventLegal);
s32 GetUnionRoomTradeMessageId(struct GFtgtGnameSub rfuPlayer, struct GFtgtGnameSub rfuPartner, u16 playerSpecies2, u16 partnerSpecies, u8 requestedType, u16 playerSpecies, u8 isEventLegal);
s32 CanRegisterMonForTradingBoard(struct RfuGameCompatibilityData rfuPlayer, u16 species2, u16 species, u8 isEventLegal);
s32 GetUnionRoomTradeMessageId(struct RfuGameCompatibilityData rfuPlayer, struct RfuGameCompatibilityData rfuPartner, u16 playerSpecies2, u16 partnerSpecies, u8 requestedType, u16 playerSpecies, u8 isEventLegal);
void CB2_ReturnToTradeMenuFromSummary(void);
#endif //GUARD_TRADE_H
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef GUARD_TRADE_SCENE_H
#define GUARD_TRADE_SCENE_H
void CB2_InitTradeAnim_LinkTrade(void);
void CB2_LinkTrade(void);
void CreateInGameTradePokemon(void);
void DoInGameTradeScene(void);
void DrawTextOnTradeWindow(u8 windowId, const u8 *str, s8 speed);
+85 -97
View File
@@ -3,58 +3,60 @@
#include "global.h"
#include "link_rfu.h"
#include "constants/union_room.h"
// Return value of IsRequestedTypeAndSpeciesInPlayerParty
#define UR_TRADE_MATCH 0
#define UR_TRADE_NOTYPE 1
#define UR_TRADE_NOEGG 2
// In the Union Room the player is only ever connected to ≤ 4 other players.
// However, there can be up to MAX_UNION_ROOM_LEADERS (8) object events to
// represent leaders of recently discovered link groups, and each of those groups
// may have up to MAX_RFU_PLAYERS (5) players in it including the leader.
// These players are represented on-screen by NPC sprites drawn around the leader.
// Thus there can be 40 sprites of other players on-screen, in 8 groups of 5.
#define NUM_UNION_ROOM_SPRITES (MAX_UNION_ROOM_LEADERS * MAX_RFU_PLAYERS)
#define UROOM_MAX_GROUP_COUNT 8
#define UROOM_MAX_PARTY_SIZE 5
// The maximum number of recently connected players that can be tracked.
// Note that this is significantly less than NUM_UNION_ROOM_SPRITES, i.e. not
// every player that can be shown in the Union Room can be tracked at once.
// Information such as a group member's gender can instead be read from partnerInfo
// of the leader's RfuGameData by tracking at least all of the group leaders.
#define MAX_RFU_PLAYER_LIST_SIZE 16
struct UnionGnameUnamePair
struct RfuPlayerData
{
struct GFtgtGname gname;
u8 ALIGNED(4) uname[PLAYER_NAME_LENGTH + 1];
struct RfuGameData data;
u8 ALIGNED(4) name[RFU_USER_NAME_LENGTH];
};
struct UnkStruct_x1C
struct RfuPlayer
{
struct UnionGnameUnamePair gname_uname;
struct RfuPlayerData rfu;
u16 timeoutCounter;
u8 groupScheduledAnim:2;
bool8 useRedText:1; // Never set
u8 newPlayerCountdown;
u8 unused;
};
struct RfuPlayerList
{
struct RfuPlayer players[MAX_RFU_PLAYER_LIST_SIZE];
};
struct RfuIncomingPlayer
{
struct RfuPlayerData rfu;
u8 active:1;
};
struct UnkStruct_x20
struct RfuIncomingPlayerList
{
struct UnionGnameUnamePair gname_uname;
u16 field_18;
u8 groupScheduledAnim:2;
bool8 field_1A_1:1;
u8 field_1B;
u32 field_1C; // unused
struct RfuIncomingPlayer players[MAX_RFU_PLAYERS];
};
// These arrays are dynamically allocated but must be
// represented as structs to match.
// Don't ask me why.
// FIXME: Find a way around this.
struct UnkStruct_Main0
struct WirelessLink_Leader
{
struct UnkStruct_x20 arr[0];
};
struct UnkStruct_Main4
{
struct UnkStruct_x1C arr[0];
};
struct UnkStruct_Leader
{
struct UnkStruct_Main0 * field_0;
struct UnkStruct_Main4 * field_4;
struct UnkStruct_Main0 * field_8;
struct RfuPlayerList * playerList;
struct RfuIncomingPlayerList * incomingPlayerList;
struct RfuPlayerList * playerListBackup;
u8 state;
u8 textState;
u8 delayTimerAfterOk;
@@ -63,36 +65,35 @@ struct UnkStruct_Leader
u8 nPlayerModeWindowId;
u8 listTaskId;
u8 playerCount;
u8 messageWindowId;
u8 field_15;
u8 field_16;
u16 yesNoWindowId;
u8 unused;
u8 listenTaskId;
u8 activity;
u8 field_19;
u16 field_1A;
u8 joinRequestAnswer;
u16 memberConfirmTimeout;
};
struct UnkStruct_Group
struct WirelessLink_Group
{
struct UnkStruct_Main0 * field_0;
struct UnkStruct_Main4 * field_4;
struct RfuPlayerList * playerList;
struct RfuIncomingPlayerList * incomingPlayerList;
u8 state;
u8 textState;
u8 field_A; // unused
u8 delayTimerAfterOk; // unused
u8 listWindowId;
u8 bButtonCancelWindowId;
u8 playerNameAndIdWindowId;
u8 listTaskId;
u8 leaderId;
u8 field_10;
u8 unused;
u8 listenTaskId;
u8 cardOrNews;
u8 field_13; // referenced but never set
bool8 isWonderNews;
bool8 showListMenu; // referenced but never set
u8 refreshTimer;
u8 delayBeforePrint;
};
struct UnionObj
struct UnionRoomObject
{
u8 state;
u8 gfxId;
@@ -100,69 +101,56 @@ struct UnionObj
u8 schedAnim;
};
struct UnkStruct_URoom
struct WirelessLink_URoom
{
/* 0x000 */ struct UnkStruct_Main0 * field_0;
/* 0x004 */ struct UnkStruct_Main4 * field_4;
/* 0x008 */ struct UnkStruct_Main0 * field_8;
/* 0x00C */ struct UnkStruct_Main4 * field_C;
/* 0x010 */ u16 field_10;
/* 0x012 */ u16 field_12;
/* 0x014 */ u8 state;
/* 0x015 */ u8 stateAfterPrint;
/* 0x016 */ u8 textState;
/* 0x017 */ u8 field_17;
/* 0x018 */ u8 field_18;
/* 0x019 */ u8 field_19;
/* 0x01A */ u8 field_1A;
/* 0x01B */ u8 topListMenuWindowId;
/* 0x01C */ u8 topListMenuListMenuId;
/* 0x01D */ u8 tradeBoardSelectWindowId;
/* 0x01E */ u8 tradeBoardDetailsWindowId;
/* 0x01F */ u8 field_1F;
/* 0x020 */ u8 field_20;
/* 0x021 */ u8 spriteIds[40];
/* 0x049 */ u8 field_49;
/* 0x04A */ u8 tradeBoardListMenuId;
// For communication with potential link partners
/* 0x04C */ u16 playerSendBuffer[6];
/* 0x058 */ u8 activityRequestStrbufs[4][11];
/* 0x084 */ u16 partnerYesNoResponse;
/* 0x086 */ u16 recvActivityRequest[3]; // activity[, species, level]
/* 0x08C */ struct UnionObj unionObjs[8];
/* 0x0AC */ u8 trainerCardStrbufs[12][15];
/* 0x160 */ u8 field_174[48];
/* 0x190 */ u8 field_1A4[200];
};
union UnkUnion_Main
{
struct UnkStruct_Leader * leader;
struct UnkStruct_Group * group;
struct UnkStruct_URoom * uRoom;
struct RfuPlayerList * playerList;
struct RfuIncomingPlayerList * incomingChildList;
struct RfuPlayerList * spawnPlayer;
struct RfuIncomingPlayerList * incomingParentList;
u16 unknown; // Never read
u16 unreadPlayerId;
u8 state;
u8 stateAfterPrint;
u8 textState;
u8 filler[4];
u8 topListMenuWindowId;
u8 topListMenuId;
u8 tradeBoardMainWindowId;
u8 tradeBoardHeaderWindowId;
u8 unused1;
u8 searchTaskId;
u8 spriteIds[NUM_UNION_ROOM_SPRITES];
u8 unused2;
u8 tradeBoardListMenuId;
// For communication with potential link partners
u16 playerSendBuffer[6];
u8 activityRequestStrbufs[4][11];
u16 partnerYesNoResponse;
u16 recvActivityRequest[3]; // activity[, species, level]
struct UnionRoomObject objects[MAX_UNION_ROOM_LEADERS];
u8 trainerCardStrBuffer[12][15];
u8 trainerCardColorStrBuffer[48];
u8 trainerCardMsgStrBuffer[200];
};
struct UnionRoomTrade
{
u16 field_0;
u16 state;
u16 type;
u32 playerPersonality;
u8 field_8;
u8 field_9;
u8 offerPlayerId;
u16 playerSpecies;
u16 playerLevel;
u16 species;
u16 level;
u16 field_12;
u32 personality;
};
extern struct GFtgtGnameSub gPartnerTgtGnameSub;
extern struct RfuGameCompatibilityData gRfuPartnerCompatibilityData;
extern u16 gUnionRoomOfferedSpecies;
extern u8 gUnionRoomRequestedMonType;
void StartUnionRoomBattle(u16 battleFlags);
u8 UnionRoom_CreateTask_CallCB2ReturnFromLinkTrade(void);
u8 CreateTask_CreateTradeMenu(void);
#endif //GUARD_UNION_ROOM_H
+16
View File
@@ -0,0 +1,16 @@
#ifndef GUARD_UNION_ROOM_PLAYER_AVATAR_H
#define GUARD_UNION_ROOM_PLAYER_AVATAR_H
#include "union_room.h"
u8 InitUnionRoomPlayerObjects(struct UnionRoomObject * players);
void DestroyUnionRoomPlayerObjects(void);
void CreateUnionRoomPlayerSprites(u8 *spriteIds, s32 leaderId);
void DestroyUnionRoomPlayerSprites(u8 *spriteIds);
void MakeGroupAssemblyAreasPassable(void);
void ScheduleUnionRoomPlayerRefresh(struct WirelessLink_URoom *uroom);
void HandleUnionRoomPlayerRefresh(struct WirelessLink_URoom *uroom);
bool32 TryInteractWithUnionRoomMember(struct RfuPlayerList *list, s16 *memberIdPtr, s16 *leaderIdPtr, u8 *spriteIds);
void UpdateUnionRoomMemberFacing(u32 memberId, u32 leaderId, struct RfuPlayerList *list);
#endif //GUARD_UNION_ROOM_PLAYER_AVATAR_H
+2 -2
View File
@@ -249,7 +249,7 @@ SECTIONS {
src/trainer_fan_club.o(.text);
src/quest_log_events.o(.text);
src/union_room.o(.text);
src/rfu_union_tool.o(.text);
src/union_room_player_avatar.o(.text);
src/union_room_battle.o(.text);
src/pokemon_special_anim.o(.text);
src/pokemon_special_anim_scene.o(.text);
@@ -542,7 +542,7 @@ SECTIONS {
src/trainer_fan_club.o(.rodata);
src/quest_log_events.o(.rodata);
src/union_room.o(.rodata);
src/rfu_union_tool.o(.rodata);
src/union_room_player_avatar.o(.rodata);
src/union_room_battle.o(.rodata);
src/union_room_message.o(.rodata);
src/pokemon_special_anim.o(.rodata);
+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;
}
+1 -1
View File
@@ -102,7 +102,7 @@
.include "src/help_message.o"
.include "src/quest_log_events.o"
.include "src/union_room.o"
.include "src/rfu_union_tool.o"
.include "src/union_room_player_avatar.o"
.include "src/union_room_battle.o"
.include "src/pokemon_special_anim.o"
.include "src/party_menu.o"