summaryrefslogtreecommitdiff
path: root/src/overworld.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/overworld.c')
-rw-r--r--src/overworld.c989
1 files changed, 535 insertions, 454 deletions
diff --git a/src/overworld.c b/src/overworld.c
index a10d1e17a..0ff8d5b7f 100644
--- a/src/overworld.c
+++ b/src/overworld.c
@@ -66,32 +66,47 @@
#include "constants/species.h"
#include "constants/weather.h"
+#define PLAYER_TRADING_STATE_IDLE 0x80
+#define PLAYER_TRADING_STATE_BUSY 0x81
+#define PLAYER_TRADING_STATE_UNK_2 0x82
+#define PLAYER_TRADING_STATE_EXITING_ROOM 0x83
+
+#define FACING_NONE 0
+#define FACING_UP 1
+#define FACING_DOWN 2
+#define FACING_LEFT 3
+#define FACING_RIGHT 4
+#define FACING_FORCED_UP 7
+#define FACING_FORCED_DOWN 8
+#define FACING_FORCED_LEFT 9
+#define FACING_FORCED_RIGHT 10
+
// event scripts
extern const u8 EventScript_WhiteOut[];
-extern const u8 EventScript_271862[];
-extern const u8 EventScript_277513[];
-extern const u8 EventScript_TradeRoom_TooBusyToNotice[];
-extern const u8 EventScript_TradeRoom_ReadTrainerCard1[];
-extern const u8 EventScript_TradeRoom_ReadTrainerCard2[];
-extern const u8 gUnknown_08277388[];
-extern const u8 gUnknown_082773A3[];
-extern const u8 gUnknown_082773BE[];
-extern const u8 gUnknown_082773D9[];
-extern const u8 gUnknown_0827741D[];
-extern const u8 gUnknown_08277432[];
-extern const u8 gUnknown_08277447[];
-extern const u8 gUnknown_0827745C[];
-extern const u8 gUnknown_08277374[];
-extern const u8 gUnknown_0827737E[];
-extern const u8 gUnknown_082773FF[];
-extern const u8 gUnknown_082773F5[];
-extern const u8 gUnknown_082774EF[];
-extern const u8 gUnknown_08277509[];
+extern const u8 EventScript_ResetMrBriney[];
+extern const u8 EventScript_DoLinkRoomExit[];
+extern const u8 gEventScript_TradeRoom_TooBusyToNotice[];
+extern const u8 gEventScript_TradeRoom_ReadTrainerCard_NoColor[];
+extern const u8 gEventScript_TradeRoom_ReadTrainerCard_Normal[];
+extern const u8 EventScript_DoubleBattleColosseum_PlayerSpot0[];
+extern const u8 EventScript_DoubleBattleColosseum_PlayerSpot1[];
+extern const u8 EventScript_DoubleBattleColosseum_PlayerSpot2[];
+extern const u8 EventScript_DoubleBattleColosseum_PlayerSpot3[];
+extern const u8 EventScript_RecordCenter_Spot0[];
+extern const u8 EventScript_RecordCenter_Spot1[];
+extern const u8 EventScript_RecordCenter_Spot2[];
+extern const u8 EventScript_RecordCenter_Spot3[];
+extern const u8 EventScript_SingleBattleColosseum_PlayerSpot0[];
+extern const u8 EventScript_SingleBattleColosseum_PlayerSpot1[];
+extern const u8 EventScript_TradeCenter_Chair1[];
+extern const u8 EventScript_TradeCenter_Chair0[];
+extern const u8 EventScript_ConfirmLeaveTradeRoom[];
+extern const u8 EventScript_TerminateLink[];
extern const struct MapLayout *const gMapLayouts[];
extern const struct MapHeader *const *const gMapGroups[];
extern const int gMaxFlashLevel;
-extern const u16 gUnknown_82EC7C4[];
+extern const u16 gOverworldBackgroundLayerFlags[];
static void Overworld_ResetStateAfterWhiteOut(void);
static void c2_80567AC(void);
@@ -106,63 +121,63 @@ static bool32 load_map_stuff(u8 *state, u32);
static bool32 map_loading_iteration_2_link(u8 *state);
static void mli4_mapscripts_and_other(void);
static void InitOverworldGraphicsRegisters(void);
-static u8 sub_8087858(u8);
-static u16 sub_80871C0(u32 a1);
+static u8 GetSpriteForLinkedPlayer(u8);
+static u16 KeyInterCB_SendNothing(u32 a1);
static void sub_80867C8(void);
static void sub_80867D8(void);
static void sub_8086AE4(void);
static void sub_80869DC(void);
static void sub_8086B14(void);
-static void sub_8086AAC(void);
+static void SetCameraToTrackGuestPlayer(void);
static void sub_8086988(bool32 arg0);
static void sub_8086A80(void);
static void sub_8086A68(void);
static void sub_8086860(void);
-static void sub_8086AC8(void);
-static void sub_8086B9C(void);
-static void sub_8086C40(void);
-static void sub_8086C90(void);
-static void sub_8086FA0(u16);
-static void sub_8086F38(u16*, s32);
-static u8 npc_something3(u8 a1, u8 a2);
+static void SetCameraToTrackGuestPlayer_2(void);
+static void CreateLinkPlayerSprites(void);
+static void ClearAllPlayerKeys(void);
+static void ResetAllTradingStates(void);
+static void UpdateHeldKeyCode(u16);
+static void UpdateAllLinkPlayers(u16*, s32);
+static u8 FlipVerticalAndClearForced(u8 a1, u8 a2);
static u8 LinkPlayerDetectCollision(u8 selfEventObjId, u8 a2, s16 x, s16 y);
static void CreateLinkPlayerSprite(u8 linkPlayerId, u8 gameVersion);
-static void sub_8087878(u8 linkPlayerId, u16 *x, u16 *y);
-static u8 sub_80878A0(u8 linkPlayerId);
-static u8 sub_80878C0(u8 linkPlayerId);
+static void GetLinkPlayerCoords(u8 linkPlayerId, u16 *x, u16 *y);
+static u8 GetLinkPlayerFacingDirection(u8 linkPlayerId);
+static u8 GetLinkPlayerElevation(u8 linkPlayerId);
static s32 sub_80878E4(u8 linkPlayerId);
static u8 GetLinkPlayerIdAt(s16 x, s16 y);
-static void sub_808796C(u8 linkPlayerId, u8 a2);
+static void SetPlayerFacingDirection(u8 linkPlayerId, u8 a2);
static void ZeroEventObject(struct EventObject *eventObj);
static void SpawnLinkPlayerEventObject(u8 linkPlayerId, s16 x, s16 y, u8 a4);
static void InitLinkPlayerEventObjectPos(struct EventObject *eventObj, s16 x, s16 y);
static void sub_80877DC(u8 linkPlayerId, u8 a2);
static void sub_808780C(u8 linkPlayerId);
-static u8 sub_8087858(u8 linkPlayerId);
+static u8 GetSpriteForLinkedPlayer(u8 linkPlayerId);
static void sub_8087584(void);
-static u32 sub_8087690(void);
+static u32 GetLinkSendQueueLength(void);
static void ZeroLinkPlayerEventObject(struct LinkPlayerEventObject *linkPlayerEventObj);
-static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1);
-static u16 sub_8087480(const u8 *script);
+static const u8 *TryInteractWithPlayer(struct TradeRoomPlayer *a1);
+static u16 GetDirectionForEventScript(const u8 *script);
static void sub_8087510(void);
-static void sub_808751C(void);
+static void InitLinkRoomStartMenuScript(void);
static void sub_8087530(const u8 *script);
-static void sub_808754C(void);
-static void sub_8087568(const u8 *script);
-static void sub_80872D8(s32 linkPlayerId, s32 a2, struct UnkStruct_8054FF8 *a3);
-static bool32 sub_8087340(struct UnkStruct_8054FF8 *a1);
-static bool32 sub_8087358(struct UnkStruct_8054FF8 *a1);
-static u8 *sub_8087370(struct UnkStruct_8054FF8 *a1);
-static bool32 sub_8087388(struct UnkStruct_8054FF8 *a1);
-static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1);
-static u16 sub_808711C(u32);
-static u16 sub_8087140(u32);
-static void sub_808709C(u16 *a1);
-static u16 sub_80870B0(u32 a1);
-static u16 sub_80870F8(u32 a1);
-static u16 sub_8087068(u16 a1);
-static void c1_link_related(void);
-static void c1_link_related_func_set(u16 (*func)(u32));
+static void CreateConfirmLeaveTradeRoomPrompt(void);
+static void InitMenuBasedScript(const u8 *script);
+static void LoadTradeRoomPlayer(s32 linkPlayerId, s32 a2, struct TradeRoomPlayer *a3);
+static bool32 sub_8087340(struct TradeRoomPlayer *a1);
+static bool32 sub_8087340_2(struct TradeRoomPlayer *a1);
+static u8 *TryGetTileEventScript(struct TradeRoomPlayer *a1);
+static bool32 PlayerIsAtSouthExit(struct TradeRoomPlayer *a1);
+static const u8 *TryInteractWithPlayer(struct TradeRoomPlayer *a1);
+static u16 KeyInterCB_DeferToRecvQueue(u32);
+static u16 KeyInterCB_DeferToSendQueue(u32);
+static void ResetPlayerHeldKeys(u16 *a1);
+static u16 KeyInterCB_SelfIdle(u32 a1);
+static u16 KeyInterCB_DeferToEventScript(u32 a1);
+static u16 GetDirectionForDpadKey(u16 a1);
+static void CB1_UpdateLinkState(void);
+static void SetKeyInterceptCallback(u16 (*func)(u32));
static void SetFieldVBlankCallback(void);
static void FieldClearVBlankHBlankCallbacks(void);
static void sub_8085810(void);
@@ -171,21 +186,24 @@ static u8 GetAdjustedInitialDirection(struct InitialPlayerAvatarState *playerStr
static u16 GetCenterScreenMetatileBehavior(void);
// IWRAM bss vars
-IWRAM_DATA static void *sUnknown_03000E0C;
-IWRAM_DATA static u8 sUnknown_03000E10[4];
-IWRAM_DATA static u16 (*sUnknown_03000E14)(u32);
-IWRAM_DATA static u8 sUnknown_03000E18;
-IWRAM_DATA static u8 sUnknown_03000E19;
+IWRAM_DATA static void *sUnusedOverworldCallback;
+IWRAM_DATA static u8 sPlayerTradingStates[4];
+// This callback is called with a player's key code. It then returns an
+// adjusted key code, effectively intercepting the input before anything
+// can process it.
+IWRAM_DATA static u16 (*sPlayerKeyInterceptCallback)(u32);
+IWRAM_DATA static bool8 sUnknown_03000E18;
+IWRAM_DATA static u8 sRfuKeepAliveTimer;
IWRAM_DATA static u32 sUnusedVar;
// IWRAM common
u16 *gBGTilemapBuffers1;
u16 *gBGTilemapBuffers2;
u16 *gBGTilemapBuffers3;
-u16 gUnknown_03005DA8;
+u16 gHeldKeyCodeToSend;
void (*gFieldCallback)(void);
bool8 (*gFieldCallback2)(void);
-u8 gUnknown_03005DB4;
+u8 gLocalLinkPlayerId; // This is our player id in a multiplayer mode.
u8 gFieldLinkPlayerCount;
// EWRAM vars
@@ -319,43 +337,47 @@ static const struct ScanlineEffectParams sFlashEffectParams =
0,
};
-static u8 sub_80879D8(struct LinkPlayerEventObject *, struct EventObject *, u8);
-static u8 sub_80879F8(struct LinkPlayerEventObject *, struct EventObject *, u8);
-static u8 sub_80879FC(struct LinkPlayerEventObject *, struct EventObject *, u8);
+static u8 MovementEventModeCB_Normal(struct LinkPlayerEventObject *, struct EventObject *, u8);
+static u8 MovementEventModeCB_Ignored(struct LinkPlayerEventObject *, struct EventObject *, u8);
+static u8 MovementEventModeCB_Normal_2(struct LinkPlayerEventObject *, struct EventObject *, u8);
-static u8 (*const gUnknown_08339DC8[])(struct LinkPlayerEventObject *, struct EventObject *, u8) =
+static u8 (*const gLinkPlayerMovementModes[])(struct LinkPlayerEventObject *, struct EventObject *, u8) =
{
- sub_80879D8,
- sub_80879F8,
- sub_80879FC,
+ MovementEventModeCB_Normal, // MOVEMENT_MODE_FREE
+ MovementEventModeCB_Ignored, // MOVEMENT_MODE_FROZEN
+ MovementEventModeCB_Normal_2, // MOVEMENT_MODE_SCRIPTED
};
-static u8 sub_8087A1C(struct LinkPlayerEventObject *, struct EventObject *, u8);
-static u8 sub_8087A20(struct LinkPlayerEventObject *, struct EventObject *, u8);
-static u8 sub_8087A88(struct LinkPlayerEventObject *, struct EventObject *, u8);
-
-static u8 (*const gUnknown_08339DD4[])(struct LinkPlayerEventObject *, struct EventObject *, u8) =
-{
- sub_8087A1C,
- sub_8087A20,
- sub_8087A20,
- sub_8087A20,
- sub_8087A20,
- sub_8087A1C,
- sub_8087A1C,
- sub_8087A88,
- sub_8087A88,
- sub_8087A88,
- sub_8087A88,
+static u8 FacingHandler_DoNothing(struct LinkPlayerEventObject *, struct EventObject *, u8);
+static u8 FacingHandler_DpadMovement(struct LinkPlayerEventObject *, struct EventObject *, u8);
+static u8 FacingHandler_ForcedFacingChange(struct LinkPlayerEventObject *, struct EventObject *, u8);
+
+// These handlers return TRUE if the movement was scripted and successful, and FALSE otherwise.
+static bool8 (*const gLinkPlayerFacingHandlers[])(struct LinkPlayerEventObject *, struct EventObject *, u8) =
+{
+ FacingHandler_DoNothing,
+ FacingHandler_DpadMovement,
+ FacingHandler_DpadMovement,
+ FacingHandler_DpadMovement,
+ FacingHandler_DpadMovement,
+ FacingHandler_DoNothing,
+ FacingHandler_DoNothing,
+ FacingHandler_ForcedFacingChange,
+ FacingHandler_ForcedFacingChange,
+ FacingHandler_ForcedFacingChange,
+ FacingHandler_ForcedFacingChange,
};
-static void sub_8087AA0(struct LinkPlayerEventObject *, struct EventObject *);
-static void sub_8087AA8(struct LinkPlayerEventObject *, struct EventObject *);
+static void MovementStatusHandler_EnterFreeMode(struct LinkPlayerEventObject *, struct EventObject *);
+static void MovementStatusHandler_TryAdvanceScript(struct LinkPlayerEventObject *, struct EventObject *);
-static void (*const gUnknown_08339E00[])(struct LinkPlayerEventObject *, struct EventObject *) =
+// These handlers are run after an attempted movement.
+static void (*const gMovementStatusHandler[])(struct LinkPlayerEventObject *, struct EventObject *) =
{
- sub_8087AA0,
- sub_8087AA8,
+ // FALSE:
+ MovementStatusHandler_EnterFreeMode,
+ // TRUE:
+ MovementStatusHandler_TryAdvanceScript,
};
// code
@@ -387,7 +409,7 @@ void Overworld_ResetStateAfterTeleport(void)
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
- ScriptContext2_RunNewScript(EventScript_271862);
+ ScriptContext2_RunNewScript(EventScript_ResetMrBriney);
}
void Overworld_ResetStateAfterDigEscRope(void)
@@ -408,10 +430,12 @@ static void Overworld_ResetStateAfterWhiteOut(void)
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
- if (VarGet(VAR_0x4039) == 1)
+ // If you were defeated by Kyogre/Groudon and the step counter has
+ // maxed out, end the unusual weather.
+ if (VarGet(VAR_SHOULD_END_UNUSUAL_WEATHER) == 1)
{
- VarSet(VAR_0x4039, 0);
- VarSet(VAR_0x4037, 0);
+ VarSet(VAR_SHOULD_END_UNUSUAL_WEATHER, 0);
+ VarSet(VAR_UNUSUAL_WEATHER_LOCATION, UNUSUAL_WEATHER_NONE);
}
}
@@ -676,7 +700,7 @@ void UpdateEscapeWarp(s16 x, s16 y)
{
u8 currMapType = GetCurrentMapType();
u8 destMapType = GetMapTypeByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum);
- if (is_map_type_1_2_3_5_or_6(currMapType) && is_map_type_1_2_3_5_or_6(destMapType) != TRUE)
+ if (IsMapTypeOutdoors(currMapType) && IsMapTypeOutdoors(destMapType) != TRUE)
SetEscapeWarp(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, x - 7, y - 6);
}
@@ -821,8 +845,8 @@ void LoadMapFromCameraTransition(u8 mapGroup, u8 mapNum)
static void mli0_load_map(u32 a1)
{
- bool8 v2;
- bool8 indoors;
+ bool8 isOutdoors;
+ bool8 isIndoors;
LoadCurrentMapData();
if (!(sUnknown_020322D8 & 1))
@@ -835,8 +859,8 @@ static void mli0_load_map(u32 a1)
LoadEventObjTemplatesFromHeader();
}
- v2 = is_map_type_1_2_3_5_or_6(gMapHeader.mapType);
- indoors = Overworld_MapTypeIsIndoors(gMapHeader.mapType);
+ isOutdoors = IsMapTypeOutdoors(gMapHeader.mapType);
+ isIndoors = IsMapTypeIndoors(gMapHeader.mapType);
sub_80EB218();
TrySetMapSaveWarpStatus();
@@ -848,7 +872,7 @@ static void mli0_load_map(u32 a1)
DoTimeBasedEvents();
SetSav1WeatherFromCurrMapHeader();
ChooseAmbientCrySpecies();
- if (v2)
+ if (isOutdoors)
FlagClear(FLAG_SYS_USE_FLASH);
SetDefaultFlashLevel();
Overworld_ClearSavedMusic();
@@ -862,7 +886,7 @@ static void mli0_load_map(u32 a1)
else
InitMap();
- if (a1 != 1 && indoors)
+ if (a1 != 1 && isIndoors)
{
UpdateTVScreensOnMap(gBackupMapLayout.width, gBackupMapLayout.height);
sub_80E9238(1);
@@ -923,7 +947,7 @@ static u8 GetAdjustedInitialTransitionFlags(struct InitialPlayerAvatarState *pla
static u8 GetAdjustedInitialDirection(struct InitialPlayerAvatarState *playerStruct, u8 transitionFlags, u16 metatileBehavior, u8 mapType)
{
- if (FlagGet(FLAG_SYS_CRUISE_MODE) && mapType == MAP_TYPE_6)
+ if (FlagGet(FLAG_SYS_CRUISE_MODE) && mapType == MAP_TYPE_OCEAN_ROUTE)
return DIR_EAST;
else if (MetatileBehavior_IsDeepSouthWarp(metatileBehavior) == TRUE)
return DIR_NORTH;
@@ -1016,7 +1040,7 @@ static bool16 ShouldLegendaryMusicPlayAtLocation(struct WarpData *warp)
case MAP_NUM(ROUTE128):
return TRUE;
default:
- if (VarGet(VAR_0x405E) < 4)
+ if (VarGet(VAR_RAYQUAZA_STATE) < 4)
return FALSE;
switch (warp->mapNum)
{
@@ -1032,7 +1056,7 @@ static bool16 ShouldLegendaryMusicPlayAtLocation(struct WarpData *warp)
static bool16 NoMusicInSotopolisWithLegendaries(struct WarpData *warp)
{
- if (VarGet(VAR_0x40CA) != 1)
+ if (VarGet(VAR_SKY_PILLAR_STATE) != 1)
return FALSE;
else if (warp->mapGroup != MAP_GROUP(SOOTOPOLIS_CITY))
return FALSE;
@@ -1057,9 +1081,9 @@ static bool16 IsInfiltratedWeatherInstitute(struct WarpData *warp)
static bool16 IsInflitratedSpaceCenter(struct WarpData *warp)
{
- if (VarGet(VAR_0x405D) == 0)
+ if (VarGet(VAR_MOSSDEEP_STATE) == 0)
return FALSE;
- else if (VarGet(VAR_0x405D) > 2)
+ else if (VarGet(VAR_MOSSDEEP_STATE) > 2)
return FALSE;
else if (warp->mapGroup != MAP_GROUP(MOSSDEEP_CITY_SPACE_CENTER_1F))
return FALSE;
@@ -1197,7 +1221,7 @@ void Overworld_ChangeMusicTo(u16 newMusic)
u8 GetMapMusicFadeoutSpeed(void)
{
const struct MapHeader *mapHeader = GetDestinationWarpMapHeader();
- if (Overworld_MapTypeIsIndoors(mapHeader->mapType) == TRUE)
+ if (IsMapTypeIndoors(mapHeader->mapType) == TRUE)
return 2;
else
return 4;
@@ -1210,7 +1234,7 @@ void TryFadeOutOldMapMusic(void)
if (FlagGet(FLAG_SPECIAL_FLAG_0x4001) != TRUE && warpMusic != GetCurrentMapMusic())
{
if (currentMusic == MUS_NAMINORI
- && VarGet(VAR_0x40CA) == 2
+ && VarGet(VAR_SKY_PILLAR_STATE) == 2
&& gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(SOOTOPOLIS_CITY)
&& gSaveBlock1Ptr->location.mapNum == MAP_NUM(SOOTOPOLIS_CITY)
&& sWarpDestination.mapGroup == MAP_GROUP(SOOTOPOLIS_CITY)
@@ -1328,13 +1352,13 @@ u8 GetLastUsedWarpMapType(void)
return GetMapTypeByWarpData(&gLastUsedWarp);
}
-bool8 is_map_type_1_2_3_5_or_6(u8 mapType)
+bool8 IsMapTypeOutdoors(u8 mapType)
{
if (mapType == MAP_TYPE_ROUTE
|| mapType == MAP_TYPE_TOWN
|| mapType == MAP_TYPE_UNDERWATER
|| mapType == MAP_TYPE_CITY
- || mapType == MAP_TYPE_6)
+ || mapType == MAP_TYPE_OCEAN_ROUTE)
return TRUE;
else
return FALSE;
@@ -1344,14 +1368,14 @@ bool8 Overworld_MapTypeAllowsTeleportAndFly(u8 mapType)
{
if (mapType == MAP_TYPE_ROUTE
|| mapType == MAP_TYPE_TOWN
- || mapType == MAP_TYPE_6
+ || mapType == MAP_TYPE_OCEAN_ROUTE
|| mapType == MAP_TYPE_CITY)
return TRUE;
else
return FALSE;
}
-bool8 Overworld_MapTypeIsIndoors(u8 mapType)
+bool8 IsMapTypeIndoors(u8 mapType)
{
if (mapType == MAP_TYPE_INDOOR
|| mapType == MAP_TYPE_SECRET_BASE)
@@ -1407,9 +1431,9 @@ static void ResetSafariZoneFlag_(void)
ResetSafariZoneFlag();
}
-bool32 is_c1_link_related_active(void)
+bool32 IsUpdateLinkStateCBActive(void)
{
- if (gMain.callback1 == c1_link_related)
+ if (gMain.callback1 == CB1_UpdateLinkState)
return TRUE;
else
return FALSE;
@@ -1476,9 +1500,10 @@ void SetMainCallback1(MainCallback cb)
gMain.callback1 = cb;
}
-void sub_8085E94(void *a0)
+// This function is never called.
+void SetUnusedCallback(void *func)
{
- sUnknown_03000E0C = a0;
+ sUnusedOverworldCallback = func;
}
static bool8 map_post_load_hook_exec(void)
@@ -1595,15 +1620,15 @@ static void c2_80567AC(void)
if (map_loading_iteration_3(&gMain.state))
{
SetFieldVBlankCallback();
- SetMainCallback1(c1_link_related);
- sub_8086C2C();
+ SetMainCallback1(CB1_UpdateLinkState);
+ ResetAllMultiplayerState();
SetMainCallback2(CB2_Overworld);
}
}
void CB2_ReturnToField(void)
{
- if (is_c1_link_related_active() == TRUE)
+ if (IsUpdateLinkStateCBActive() == TRUE)
{
SetMainCallback2(CB2_ReturnToFieldLink);
}
@@ -1629,12 +1654,12 @@ void CB2_ReturnToFieldLink(void)
SetMainCallback2(CB2_Overworld);
}
-void c2_8056854(void)
+void CB2_ReturnToFieldFromMultiplayer(void)
{
FieldClearVBlankHBlankCallbacks();
StopMapMusic();
- SetMainCallback1(c1_link_related);
- sub_8086C2C();
+ SetMainCallback1(CB1_UpdateLinkState);
+ ResetAllMultiplayerState();
if (gWirelessCommType != 0)
gFieldCallback = sub_80AF314;
@@ -1810,7 +1835,7 @@ static bool32 map_loading_iteration_3(u8 *state)
sub_8086AE4();
sub_80869DC();
sub_8086B14();
- sub_8086AAC();
+ SetCameraToTrackGuestPlayer();
(*state)++;
break;
case 4:
@@ -1980,9 +2005,9 @@ static bool32 map_loading_iteration_2_link(u8 *state)
(*state)++;
break;
case 2:
- sub_8086B9C();
+ CreateLinkPlayerSprites();
sub_8086A68();
- sub_8086AC8();
+ SetCameraToTrackGuestPlayer_2();
(*state)++;
break;
case 3:
@@ -2083,7 +2108,7 @@ static void InitOverworldGraphicsRegisters(void)
SetGpuReg(REG_OFFSET_WIN0V, 0xFF);
SetGpuReg(REG_OFFSET_WIN1H, 0xFFFF);
SetGpuReg(REG_OFFSET_WIN1V, 0xFFFF);
- SetGpuReg(REG_OFFSET_BLDCNT, gUnknown_82EC7C4[1] | gUnknown_82EC7C4[2] | gUnknown_82EC7C4[3]
+ SetGpuReg(REG_OFFSET_BLDCNT, gOverworldBackgroundLayerFlags[1] | gOverworldBackgroundLayerFlags[2] | gOverworldBackgroundLayerFlags[3]
| BLDCNT_TGT2_OBJ | BLDCNT_EFFECT_BLEND);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(13, 7));
InitOverworldBgs();
@@ -2169,21 +2194,25 @@ static void sub_8086A80(void)
InitCameraUpdateCallback(gPlayerAvatar.spriteId);
}
-static void sub_8086AAC(void)
+static void SetCameraToTrackGuestPlayer(void)
{
- InitCameraUpdateCallback(sub_8087858(gUnknown_03005DB4));
+ InitCameraUpdateCallback(GetSpriteForLinkedPlayer(gLocalLinkPlayerId));
}
-static void sub_8086AC8(void)
+// Duplicate function.
+static void SetCameraToTrackGuestPlayer_2(void)
{
- InitCameraUpdateCallback(sub_8087858(gUnknown_03005DB4));
+ InitCameraUpdateCallback(GetSpriteForLinkedPlayer(gLocalLinkPlayerId));
}
static void sub_8086AE4(void)
{
u16 x, y;
GetCameraFocusCoords(&x, &y);
- sub_8088B3C(x + gUnknown_03005DB4, y);
+
+ // This is a hack of some kind; it's undone in sub_8086B14, which is called
+ // soon after this function.
+ sub_8088B3C(x + gLocalLinkPlayerId, y);
}
static void sub_8086B14(void)
@@ -2192,7 +2221,7 @@ static void sub_8086B14(void)
u16 x, y;
GetCameraFocusCoords(&x, &y);
- x -= gUnknown_03005DB4;
+ x -= gLocalLinkPlayerId;
for (i = 0; i < gFieldLinkPlayerCount; i++)
{
@@ -2200,161 +2229,180 @@ static void sub_8086B14(void)
CreateLinkPlayerSprite(i, gLinkPlayers[i].version);
}
- sub_8086C40();
+ ClearAllPlayerKeys();
}
-static void sub_8086B9C(void)
+static void CreateLinkPlayerSprites(void)
{
u16 i;
for (i = 0; i < gFieldLinkPlayerCount; i++)
CreateLinkPlayerSprite(i, gLinkPlayers[i].version);
}
-static void c1_link_related(void)
+
+static void CB1_UpdateLinkState(void)
{
- if (gWirelessCommType == 0 || !sub_800F0B8() || !sub_8009F3C())
+ if (gWirelessCommType == 0 || !IsRfuRecvQueueEmpty() || !IsSendingKeysToLink())
{
- u8 var = gUnknown_03005DB4;
- sub_8086F38(gLinkPartnersHeldKeys, var);
- sub_8086FA0(sUnknown_03000E14(var));
- sub_8086C40();
+ u8 selfId = gLocalLinkPlayerId;
+ UpdateAllLinkPlayers(gLinkPartnersHeldKeys, selfId);
+
+ // Note: Because guestId is between 0 and 4, while the smallest key code is
+ // LINK_KEY_CODE_EMPTY, this is functionally equivalent to `sPlayerKeyInterceptCallback(0)`.
+ // It is expecting the callback to be KeyInterCB_SelfIdle, and that will
+ // completely ignore any input parameters.
+ //
+ // UpdateHeldKeyCode performs a sanity check on its input; if
+ // sPlayerKeyInterceptCallback echoes back the argument, which is selfId, then
+ // it'll use LINK_KEY_CODE_EMPTY instead.
+ //
+ // Note 2: There are some key intercept callbacks that treat the key as a player
+ // ID. It's so hacky.
+ UpdateHeldKeyCode(sPlayerKeyInterceptCallback(selfId));
+ ClearAllPlayerKeys();
}
}
-void sub_8086C2C(void)
+void ResetAllMultiplayerState(void)
{
- sub_8086C90();
- c1_link_related_func_set(sub_80870B0);
+ ResetAllTradingStates();
+ SetKeyInterceptCallback(KeyInterCB_SelfIdle);
}
-static void sub_8086C40(void)
+static void ClearAllPlayerKeys(void)
{
- sub_808709C(gLinkPartnersHeldKeys);
+ ResetPlayerHeldKeys(gLinkPartnersHeldKeys);
}
-static void c1_link_related_func_set(u16 (*func)(u32))
+static void SetKeyInterceptCallback(u16 (*func)(u32))
{
- sUnknown_03000E19 = 0;
- sUnknown_03000E14 = func;
+ sRfuKeepAliveTimer = 0;
+ sPlayerKeyInterceptCallback = func;
}
-static void sub_8086C64(void)
+// Once every ~60 frames, if the link state hasn't changed (timer reset by calls
+// to SetKeyInterceptCallback), it does a bunch of sanity checks on the connection.
+// I'm not sure if sRfuKeepAliveTimer is reset in the process, though; rfu stuff is
+// still undocumented.
+static void CheckRfuKeepAliveTimer(void)
{
- if (gWirelessCommType != 0 && ++sUnknown_03000E19 > 60)
+ if (gWirelessCommType != 0 && ++sRfuKeepAliveTimer > 60)
sub_8010198();
}
-static void sub_8086C90(void)
+static void ResetAllTradingStates(void)
{
s32 i;
for (i = 0; i < 4; i++)
- sUnknown_03000E10[i] = 0x80;
+ sPlayerTradingStates[i] = PLAYER_TRADING_STATE_IDLE;
}
-static bool32 sub_8086CA8(u16 a1)
+// Returns true if all connected players are in tradingState.
+static bool32 AreAllPlayersInTradingState(u16 tradingState)
{
s32 i;
s32 count = gFieldLinkPlayerCount;
for (i = 0; i < count; i++)
- if (sUnknown_03000E10[i] != a1)
+ if (sPlayerTradingStates[i] != tradingState)
return FALSE;
return TRUE;
}
-static bool32 sub_8086CE0(u16 a1)
+static bool32 IsAnyPlayerInTradingState(u16 tradingState)
{
s32 i;
s32 count = gFieldLinkPlayerCount;
for (i = 0; i < count; i++)
- if (sUnknown_03000E10[i] == a1)
+ if (sPlayerTradingStates[i] == tradingState)
return TRUE;
return FALSE;
}
-static void sub_8086D18(u32 a1, u16 a2, struct UnkStruct_8054FF8 *a3, u16 *a4)
+static void HandleLinkPlayerKeyInput(u32 playerId, u16 key, struct TradeRoomPlayer *trainer, u16 *forceFacing)
{
const u8 *script;
- if (sUnknown_03000E10[a1] == 0x80)
+ if (sPlayerTradingStates[playerId] == PLAYER_TRADING_STATE_IDLE)
{
- script = sub_8087370(a3);
+ script = TryGetTileEventScript(trainer);
if (script)
{
- *a4 = sub_8087480(script);
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ *forceFacing = GetDirectionForEventScript(script);
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_80870F8);
+ SetKeyInterceptCallback(KeyInterCB_DeferToEventScript);
sub_8087530(script);
}
return;
}
- if (sub_8086CE0(0x83) == 1)
+ if (IsAnyPlayerInTradingState(PLAYER_TRADING_STATE_EXITING_ROOM) == TRUE)
{
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_80870F8);
+ SetKeyInterceptCallback(KeyInterCB_DeferToEventScript);
sub_8087584();
}
return;
}
- switch (a2)
+
+ switch (key)
{
- case 24:
- if (sub_8087358(a3))
+ case LINK_KEY_CODE_START_BUTTON:
+ if (sub_8087340_2(trainer))
{
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_80870F8);
- sub_808751C();
+ SetKeyInterceptCallback(KeyInterCB_DeferToEventScript);
+ InitLinkRoomStartMenuScript();
}
}
break;
- case 18:
- if (sub_8087388(a3) == TRUE)
+ case LINK_KEY_CODE_DPAD_DOWN:
+ if (PlayerIsAtSouthExit(trainer) == TRUE)
{
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_80870F8);
- sub_808754C();
+ SetKeyInterceptCallback(KeyInterCB_DeferToEventScript);
+ CreateConfirmLeaveTradeRoomPrompt();
}
}
break;
- case 25:
- script = sub_80873B4(a3);
+ case LINK_KEY_CODE_A_BUTTON:
+ script = TryInteractWithPlayer(trainer);
if (script)
{
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_80870F8);
- sub_8087568(script);
+ SetKeyInterceptCallback(KeyInterCB_DeferToEventScript);
+ InitMenuBasedScript(script);
}
}
break;
- case 27:
- if (sub_8087340(a3))
+ case LINK_KEY_CODE_HANDLE_RECV_QUEUE:
+ if (sub_8087340(trainer))
{
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_808711C);
+ SetKeyInterceptCallback(KeyInterCB_DeferToRecvQueue);
sub_8087510();
}
}
break;
- case 28:
- if (sub_8087340(a3))
+ case LINK_KEY_CODE_HANDLE_SEND_QUEUE:
+ if (sub_8087340(trainer))
{
- sUnknown_03000E10[a1] = 0x81;
- if (a3->b)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
+ if (trainer->isLocalPlayer)
{
- c1_link_related_func_set(sub_8087140);
+ SetKeyInterceptCallback(KeyInterCB_DeferToSendQueue);
sub_8087510();
}
}
@@ -2362,388 +2410,403 @@ static void sub_8086D18(u32 a1, u16 a2, struct UnkStruct_8054FF8 *a3, u16 *a4)
}
}
- switch (a2)
+ switch (key)
{
- case 23:
- sUnknown_03000E10[a1] = 0x83;
+ case LINK_KEY_CODE_EXIT_ROOM:
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_EXITING_ROOM;
break;
- case 22:
- sUnknown_03000E10[a1] = 0x82;
+ case LINK_KEY_CODE_UNK_2:
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_UNK_2;
break;
- case 26:
- sUnknown_03000E10[a1] = 0x80;
- if (a3->b)
- c1_link_related_func_set(sub_80870B0);
+ case LINK_KEY_CODE_UNK_4:
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_IDLE;
+ if (trainer->isLocalPlayer)
+ SetKeyInterceptCallback(KeyInterCB_SelfIdle);
break;
- case 29:
- if (sUnknown_03000E10[a1] == 0x82)
- sUnknown_03000E10[a1] = 0x81;
+ case LINK_KEY_CODE_UNK_7:
+ if (sPlayerTradingStates[playerId] == PLAYER_TRADING_STATE_UNK_2)
+ sPlayerTradingStates[playerId] = PLAYER_TRADING_STATE_BUSY;
break;
}
}
-static void sub_8086F38(u16 *a1, s32 a2)
+static void UpdateAllLinkPlayers(u16 *keys, s32 selfId)
{
- struct UnkStruct_8054FF8 st;
+ struct TradeRoomPlayer trainer;
s32 i;
for (i = 0; i < 4; i++)
{
- u8 v5 = a1[i];
- u16 v8 = 0;
- sub_80872D8(i, a2, &st);
- sub_8086D18(i, v5, &st, &v8);
- if (sUnknown_03000E10[i] == 0x80)
- v8 = sub_8087068(v5);
- sub_808796C(i, v8);
+ u8 key = keys[i];
+ u16 setFacing = FACING_NONE;
+ LoadTradeRoomPlayer(i, selfId, &trainer);
+ HandleLinkPlayerKeyInput(i, key, &trainer, &setFacing);
+ if (sPlayerTradingStates[i] == PLAYER_TRADING_STATE_IDLE)
+ setFacing = GetDirectionForDpadKey(key);
+ SetPlayerFacingDirection(i, setFacing);
}
}
-static void sub_8086FA0(u16 a1)
+static void UpdateHeldKeyCode(u16 key)
{
- if (a1 >= 17 && a1 < 30)
- gUnknown_03005DA8 = a1;
+ if (key >= LINK_KEY_CODE_EMPTY && key < LINK_KEY_CODE_UNK_8)
+ gHeldKeyCodeToSend = key;
else
- gUnknown_03005DA8 = 17;
+ gHeldKeyCodeToSend = LINK_KEY_CODE_EMPTY;
if (gWirelessCommType != 0
- && sub_8087690() > 1
- && is_c1_link_related_active() == TRUE
- && sub_8009F3C() == TRUE)
+ && GetLinkSendQueueLength() > 1
+ && IsUpdateLinkStateCBActive() == TRUE
+ && IsSendingKeysToLink() == TRUE)
{
- switch (a1)
+ switch (key)
{
- case 17:
- case 18:
- case 19:
- case 20:
- case 21:
- case 24:
- case 25:
- gUnknown_03005DA8 = 0;
+ case LINK_KEY_CODE_EMPTY:
+ case LINK_KEY_CODE_DPAD_DOWN:
+ case LINK_KEY_CODE_DPAD_UP:
+ case LINK_KEY_CODE_DPAD_LEFT:
+ case LINK_KEY_CODE_DPAD_RIGHT:
+ case LINK_KEY_CODE_START_BUTTON:
+ case LINK_KEY_CODE_A_BUTTON:
+ gHeldKeyCodeToSend = LINK_KEY_CODE_NULL;
break;
}
}
}
-static u16 sub_808700C(u32 a1)
+static u16 KeyInterCB_ReadButtons(u32 key)
{
if (gMain.heldKeys & DPAD_UP)
- return 19;
+ return LINK_KEY_CODE_DPAD_UP;
else if (gMain.heldKeys & DPAD_DOWN)
- return 18;
+ return LINK_KEY_CODE_DPAD_DOWN;
else if (gMain.heldKeys & DPAD_LEFT)
- return 20;
+ return LINK_KEY_CODE_DPAD_LEFT;
else if (gMain.heldKeys & DPAD_RIGHT)
- return 21;
+ return LINK_KEY_CODE_DPAD_RIGHT;
else if (gMain.newKeys & START_BUTTON)
- return 24;
+ return LINK_KEY_CODE_START_BUTTON;
else if (gMain.newKeys & A_BUTTON)
- return 25;
+ return LINK_KEY_CODE_A_BUTTON;
else
- return 17;
+ return LINK_KEY_CODE_EMPTY;
}
-static u16 sub_8087068(u16 a1)
+static u16 GetDirectionForDpadKey(u16 a1)
{
switch (a1)
{
- case 21:
- return 4;
- case 20:
- return 3;
- case 19:
- return 1;
- case 18:
- return 2;
+ case LINK_KEY_CODE_DPAD_RIGHT:
+ return FACING_RIGHT;
+ case LINK_KEY_CODE_DPAD_LEFT:
+ return FACING_LEFT;
+ case LINK_KEY_CODE_DPAD_UP:
+ return FACING_UP;
+ case LINK_KEY_CODE_DPAD_DOWN:
+ return FACING_DOWN;
default:
- return 0;
+ return FACING_NONE;
}
}
-static void sub_808709C(u16 *a1)
+// Overwrites the keys with 0x11
+static void ResetPlayerHeldKeys(u16 *keys)
{
s32 i;
for (i = 0; i < 4; i++)
- a1[i] = 17;
+ keys[i] = LINK_KEY_CODE_EMPTY;
}
-static u16 sub_80870B0(u32 a1)
+
+static u16 KeyInterCB_SelfIdle(u32 key)
{
- if (ScriptContext2_IsEnabled() == 1)
- return 17;
- if (sub_800B4DC() > 4)
- return 27;
- if (sub_8087690() <= 4)
- return sub_808700C(a1);
- return 28;
+ if (ScriptContext2_IsEnabled() == TRUE)
+ return LINK_KEY_CODE_EMPTY;
+ if (GetLinkRecvQueueLength() > 4)
+ return LINK_KEY_CODE_HANDLE_RECV_QUEUE;
+ if (GetLinkSendQueueLength() <= 4)
+ return KeyInterCB_ReadButtons(key);
+ return LINK_KEY_CODE_HANDLE_SEND_QUEUE;
}
-static u16 sub_80870EC(u32 a1)
+static u16 sub_80870EC(u32 key)
{
- sub_8086C64();
- return 17;
+ CheckRfuKeepAliveTimer();
+ return LINK_KEY_CODE_EMPTY;
}
-static u16 sub_80870F8(u32 a1)
+// Ignore the player's inputs as long as there is an event script
+// in ScriptContext2.
+static u16 KeyInterCB_DeferToEventScript(u32 key)
{
u16 retVal;
if (ScriptContext2_IsEnabled() == TRUE)
{
- retVal = 17;
+ retVal = LINK_KEY_CODE_EMPTY;
}
else
{
- retVal = 26;
- c1_link_related_func_set(sub_80870EC);
+ retVal = LINK_KEY_CODE_UNK_4;
+ SetKeyInterceptCallback(sub_80870EC);
}
return retVal;
}
-static u16 sub_808711C(u32 a1)
+// Ignore the player's inputs as long as there are events being recived.
+static u16 KeyInterCB_DeferToRecvQueue(u32 key)
{
u16 retVal;
- if (sub_800B4DC() > 2)
+ if (GetLinkRecvQueueLength() > 2)
{
- retVal = 17;
+ retVal = LINK_KEY_CODE_EMPTY;
}
else
{
- retVal = 26;
+ retVal = LINK_KEY_CODE_UNK_4;
ScriptContext2_Disable();
- c1_link_related_func_set(sub_80870EC);
+ SetKeyInterceptCallback(sub_80870EC);
}
return retVal;
}
-static u16 sub_8087140(u32 a1)
+// Ignore the player's inputs as long as there are events being sent.
+static u16 KeyInterCB_DeferToSendQueue(u32 key)
{
u16 retVal;
- if (sub_8087690() > 2)
+ if (GetLinkSendQueueLength() > 2)
{
- retVal = 17;
+ retVal = LINK_KEY_CODE_EMPTY;
}
else
{
- retVal = 26;
+ retVal = LINK_KEY_CODE_UNK_4;
ScriptContext2_Disable();
- c1_link_related_func_set(sub_80870EC);
+ SetKeyInterceptCallback(sub_80870EC);
}
return retVal;
}
-static u16 sub_8087164(u32 a1)
+static u16 KeyInterCB_DoNothingAndKeepAlive(u32 key)
{
- sub_8086C64();
- return 17;
+ CheckRfuKeepAliveTimer();
+ return LINK_KEY_CODE_EMPTY;
}
-static u16 sub_8087170(u32 linkPlayerId)
+static u16 sub_8087170(u32 keyOrPlayerId)
{
- if (sUnknown_03000E10[linkPlayerId] == 0x82)
+ if (sPlayerTradingStates[keyOrPlayerId] == PLAYER_TRADING_STATE_UNK_2)
{
if (gMain.newKeys & B_BUTTON)
{
- c1_link_related_func_set(sub_8087164);
- return 29;
+ SetKeyInterceptCallback(KeyInterCB_DoNothingAndKeepAlive);
+ return LINK_KEY_CODE_UNK_7;
}
else
{
- return 17;
+ return LINK_KEY_CODE_EMPTY;
}
}
else
{
- sub_8086C64();
- return 17;
+ CheckRfuKeepAliveTimer();
+ return LINK_KEY_CODE_EMPTY;
}
}
static u16 sub_80871AC(u32 a1)
{
- c1_link_related_func_set(sub_8087170);
- return 22;
+ SetKeyInterceptCallback(sub_8087170);
+ return LINK_KEY_CODE_UNK_2;
}
-static u16 sub_80871C0(u32 a1)
+static u16 KeyInterCB_SendNothing(u32 key)
{
- return 17;
+ return LINK_KEY_CODE_EMPTY;
}
-static u16 sub_80871C4(u32 a1)
+static u16 KeyInterCB_WaitForPlayersToExit(u32 keyOrPlayerId)
{
- if (sUnknown_03000E10[a1] != 0x83)
- sub_8086C64();
- if (sub_8086CA8(0x83) == TRUE)
+ // keyOrPlayerId could be any keycode. This callback does no sanity checking
+ // on the size of the key. It's assuming that it is being called from
+ // CB1_UpdateLinkState.
+ if (sPlayerTradingStates[keyOrPlayerId] != PLAYER_TRADING_STATE_EXITING_ROOM)
+ CheckRfuKeepAliveTimer();
+ if (AreAllPlayersInTradingState(PLAYER_TRADING_STATE_EXITING_ROOM) == TRUE)
{
- ScriptContext1_SetupScript(EventScript_277513);
- c1_link_related_func_set(sub_80871C0);
+ ScriptContext1_SetupScript(EventScript_DoLinkRoomExit);
+ SetKeyInterceptCallback(KeyInterCB_SendNothing);
}
- return 17;
+ return LINK_KEY_CODE_EMPTY;
}
-static u16 sub_80871FC(u32 a1)
+static u16 KeyInterCB_SendExitRoomKey(u32 key)
{
- c1_link_related_func_set(sub_80871C4);
- return 23;
+ SetKeyInterceptCallback(KeyInterCB_WaitForPlayersToExit);
+ return LINK_KEY_CODE_EXIT_ROOM;
}
-static u16 sub_8087210(u32 a1)
+// Duplicate function.
+static u16 KeyInterCB_SendNothing_2(u32 key)
{
- return 17;
+ return LINK_KEY_CODE_EMPTY;
}
u32 sub_8087214(void)
{
- if (sub_8086CE0(0x83) == TRUE)
+ if (IsAnyPlayerInTradingState(PLAYER_TRADING_STATE_EXITING_ROOM) == TRUE)
return 2;
- if (sUnknown_03000E14 == sub_8087170 && sUnknown_03000E10[gUnknown_03005DB4] != 0x82)
+ if (sPlayerKeyInterceptCallback == sub_8087170 && sPlayerTradingStates[gLocalLinkPlayerId] != PLAYER_TRADING_STATE_UNK_2)
return 0;
- if (sUnknown_03000E14 == sub_8087164 && sUnknown_03000E10[gUnknown_03005DB4] == 0x81)
+ if (sPlayerKeyInterceptCallback == KeyInterCB_DoNothingAndKeepAlive && sPlayerTradingStates[gLocalLinkPlayerId] == PLAYER_TRADING_STATE_BUSY)
return 2;
- if (sub_8086CA8(0x82) != 0)
+ if (AreAllPlayersInTradingState(PLAYER_TRADING_STATE_UNK_2) != FALSE)
return 1;
return 0;
}
bool32 sub_808727C(void)
{
- return sub_8086CE0(0x83);
+ return IsAnyPlayerInTradingState(PLAYER_TRADING_STATE_EXITING_ROOM);
}
u16 sub_8087288(void)
{
- c1_link_related_func_set(sub_80871AC);
+ SetKeyInterceptCallback(sub_80871AC);
return 0;
}
u16 sub_808729C(void)
{
- c1_link_related_func_set(sub_80870F8);
+ SetKeyInterceptCallback(KeyInterCB_DeferToEventScript);
return 0;
}
-u16 sub_80872B0(void)
+// The exit room key will be sent at the next opportunity.
+// The return value is meaningless.
+u16 QueueExitLinkRoomKey(void)
{
- c1_link_related_func_set(sub_80871FC);
+ SetKeyInterceptCallback(KeyInterCB_SendExitRoomKey);
return 0;
}
u16 sub_80872C4(void)
{
- c1_link_related_func_set(sub_8087210);
+ SetKeyInterceptCallback(KeyInterCB_SendNothing_2);
return 0;
}
-static void sub_80872D8(s32 linkPlayerId, s32 a2, struct UnkStruct_8054FF8 *a3)
+static void LoadTradeRoomPlayer(s32 linkPlayerId, s32 myPlayerId, struct TradeRoomPlayer *trainer)
{
s16 x, y;
- a3->a = linkPlayerId;
- a3->b = (linkPlayerId == a2) ? 1 : 0;
- a3->c = gLinkPlayerEventObjects[linkPlayerId].mode;
- a3->d = sub_80878A0(linkPlayerId);
- sub_8087878(linkPlayerId, &x, &y);
- a3->sub.x = x;
- a3->sub.y = y;
- a3->sub.height = sub_80878C0(linkPlayerId);
- a3->field_C = MapGridGetMetatileBehaviorAt(x, y);
+ trainer->playerId = linkPlayerId;
+ trainer->isLocalPlayer = (linkPlayerId == myPlayerId) ? 1 : 0;
+ trainer->c = gLinkPlayerEventObjects[linkPlayerId].movementMode;
+ trainer->facing = GetLinkPlayerFacingDirection(linkPlayerId);
+ GetLinkPlayerCoords(linkPlayerId, &x, &y);
+ trainer->pos.x = x;
+ trainer->pos.y = y;
+ trainer->pos.height = GetLinkPlayerElevation(linkPlayerId);
+ trainer->field_C = MapGridGetMetatileBehaviorAt(x, y);
}
-static bool32 sub_8087340(struct UnkStruct_8054FF8 *a1)
+static bool32 sub_8087340(struct TradeRoomPlayer *player)
{
- u8 v1 = a1->c;
- if (v1 == 2 || v1 == 0)
+ u8 v1 = player->c;
+ if (v1 == MOVEMENT_MODE_SCRIPTED || v1 == MOVEMENT_MODE_FREE)
return TRUE;
else
return FALSE;
}
-static bool32 sub_8087358(struct UnkStruct_8054FF8 *a1)
+// Duplicate function.
+static bool32 sub_8087340_2(struct TradeRoomPlayer *player)
{
- u8 v1 = a1->c;
- if (v1 == 2 || v1 == 0)
+ u8 v1 = player->c;
+ if (v1 == MOVEMENT_MODE_SCRIPTED || v1 == MOVEMENT_MODE_FREE)
return TRUE;
else
return FALSE;
}
-static u8 *sub_8087370(struct UnkStruct_8054FF8 *a1)
+static u8 *TryGetTileEventScript(struct TradeRoomPlayer *player)
{
- if (a1->c != 2)
- return 0;
- return GetCoordEventScriptAtMapPosition(&a1->sub);
+ if (player->c != MOVEMENT_MODE_SCRIPTED)
+ return FACING_NONE;
+ return GetCoordEventScriptAtMapPosition(&player->pos);
}
-static bool32 sub_8087388(struct UnkStruct_8054FF8 *a1)
+static bool32 PlayerIsAtSouthExit(struct TradeRoomPlayer *player)
{
- if (a1->c != 2 && a1->c != 0)
+ if (player->c != MOVEMENT_MODE_SCRIPTED && player->c != MOVEMENT_MODE_FREE)
return FALSE;
- else if (!MetatileBehavior_IsSouthArrowWarp(a1->field_C))
+ else if (!MetatileBehavior_IsSouthArrowWarp(player->field_C))
return FALSE;
- else if (a1->d != 1)
+ else if (player->facing != 1)
return FALSE;
else
return TRUE;
}
-static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1)
+static const u8 *TryInteractWithPlayer(struct TradeRoomPlayer *player)
{
- struct MapPosition unkStruct;
+ struct MapPosition otherPlayerPos;
u8 linkPlayerId;
- if (a1->c && a1->c != 2)
- return 0;
+ if (player->c != MOVEMENT_MODE_FREE && player->c != MOVEMENT_MODE_SCRIPTED)
+ return FACING_NONE;
- unkStruct = a1->sub;
- unkStruct.x += gDirectionToVectors[a1->d].x;
- unkStruct.y += gDirectionToVectors[a1->d].y;
- unkStruct.height = 0;
- linkPlayerId = GetLinkPlayerIdAt(unkStruct.x, unkStruct.y);
+ otherPlayerPos = player->pos;
+ otherPlayerPos.x += gDirectionToVectors[player->facing].x;
+ otherPlayerPos.y += gDirectionToVectors[player->facing].y;
+ otherPlayerPos.height = 0;
+ linkPlayerId = GetLinkPlayerIdAt(otherPlayerPos.x, otherPlayerPos.y);
if (linkPlayerId != 4)
{
- if (!a1->b)
- return EventScript_TradeRoom_TooBusyToNotice;
- else if (sUnknown_03000E10[linkPlayerId] != 0x80)
- return EventScript_TradeRoom_TooBusyToNotice;
- else if (!sub_80B39D4(linkPlayerId))
- return EventScript_TradeRoom_ReadTrainerCard1;
+ if (!player->isLocalPlayer)
+ return gEventScript_TradeRoom_TooBusyToNotice;
+ else if (sPlayerTradingStates[linkPlayerId] != PLAYER_TRADING_STATE_IDLE)
+ return gEventScript_TradeRoom_TooBusyToNotice;
+ else if (!GetLinkTrainerCardColor(linkPlayerId))
+ return gEventScript_TradeRoom_ReadTrainerCard_NoColor;
else
- return EventScript_TradeRoom_ReadTrainerCard2;
- }
-
- return GetInteractedLinkPlayerScript(&unkStruct, a1->field_C, a1->d);
-}
-
-static u16 sub_8087480(const u8 *script)
-{
- if (script == gUnknown_08277388)
- return 10;
- else if (script == gUnknown_082773A3)
- return 9;
- else if (script == gUnknown_082773BE)
- return 10;
- else if (script == gUnknown_082773D9)
- return 9;
- else if (script == gUnknown_0827741D)
- return 10;
- else if (script == gUnknown_08277432)
- return 9;
- else if (script == gUnknown_08277447)
- return 10;
- else if (script == gUnknown_0827745C)
- return 9;
- else if (script == gUnknown_08277374)
- return 10;
- else if (script == gUnknown_0827737E)
- return 9;
- else if (script == gUnknown_082773F5)
- return 10;
- else if (script == gUnknown_082773FF)
- return 9;
+ return gEventScript_TradeRoom_ReadTrainerCard_Normal;
+ }
+
+ return GetInteractedLinkPlayerScript(&otherPlayerPos, player->field_C, player->facing);
+}
+
+// This returns which direction to force the player to look when one of
+// these event scripts runs.
+static u16 GetDirectionForEventScript(const u8 *script)
+{
+ if (script == EventScript_DoubleBattleColosseum_PlayerSpot0)
+ return FACING_FORCED_RIGHT;
+ else if (script == EventScript_DoubleBattleColosseum_PlayerSpot1)
+ return FACING_FORCED_LEFT;
+ else if (script == EventScript_DoubleBattleColosseum_PlayerSpot2)
+ return FACING_FORCED_RIGHT;
+ else if (script == EventScript_DoubleBattleColosseum_PlayerSpot3)
+ return FACING_FORCED_LEFT;
+ else if (script == EventScript_RecordCenter_Spot0)
+ return FACING_FORCED_RIGHT;
+ else if (script == EventScript_RecordCenter_Spot1)
+ return FACING_FORCED_LEFT;
+ else if (script == EventScript_RecordCenter_Spot2)
+ return FACING_FORCED_RIGHT;
+ else if (script == EventScript_RecordCenter_Spot3)
+ return FACING_FORCED_LEFT;
+ else if (script == EventScript_SingleBattleColosseum_PlayerSpot0)
+ return FACING_FORCED_RIGHT;
+ else if (script == EventScript_SingleBattleColosseum_PlayerSpot1)
+ return FACING_FORCED_LEFT;
+ else if (script == EventScript_TradeCenter_Chair0)
+ return FACING_FORCED_RIGHT;
+ else if (script == EventScript_TradeCenter_Chair1)
+ return FACING_FORCED_LEFT;
else
- return 0;
+ return FACING_NONE;
}
static void sub_8087510(void)
@@ -2751,7 +2814,7 @@ static void sub_8087510(void)
ScriptContext2_Enable();
}
-static void sub_808751C(void)
+static void InitLinkRoomStartMenuScript(void)
{
PlaySE(SE_WIN_OPEN);
ShowStartMenu();
@@ -2765,14 +2828,14 @@ static void sub_8087530(const u8 *script)
ScriptContext2_Enable();
}
-static void sub_808754C(void)
+static void CreateConfirmLeaveTradeRoomPrompt(void)
{
PlaySE(SE_WIN_OPEN);
- ScriptContext1_SetupScript(gUnknown_082774EF);
+ ScriptContext1_SetupScript(EventScript_ConfirmLeaveTradeRoom);
ScriptContext2_Enable();
}
-static void sub_8087568(const u8 *script)
+static void InitMenuBasedScript(const u8 *script)
{
PlaySE(SE_SELECT);
ScriptContext1_SetupScript(script);
@@ -2781,18 +2844,18 @@ static void sub_8087568(const u8 *script)
static void sub_8087584(void)
{
- ScriptContext1_SetupScript(gUnknown_08277509);
+ ScriptContext1_SetupScript(EventScript_TerminateLink);
ScriptContext2_Enable();
}
bool32 sub_8087598(void)
{
- if (!is_c1_link_related_active())
- return 0;
- if (sub_800B4DC() >= 3)
- sUnknown_03000E18 = 1;
+ if (!IsUpdateLinkStateCBActive())
+ return FALSE;
+ if (GetLinkRecvQueueLength() >= 3)
+ sUnknown_03000E18 = TRUE;
else
- sUnknown_03000E18 = 0;
+ sUnknown_03000E18 = FALSE;
return sUnknown_03000E18;
}
@@ -2800,19 +2863,19 @@ bool32 sub_80875C8(void)
{
u8 temp;
- if (sub_800B4DC() < 2)
+ if (GetLinkRecvQueueLength() < 2)
return FALSE;
- else if (is_c1_link_related_active() != TRUE)
+ else if (IsUpdateLinkStateCBActive() != TRUE)
return FALSE;
- else if (sub_8009F3C() != TRUE)
+ else if (IsSendingKeysToLink() != TRUE)
return FALSE;
- else if (sUnknown_03000E14 == sub_808711C)
+ else if (sPlayerKeyInterceptCallback == KeyInterCB_DeferToRecvQueue)
return TRUE;
- else if (sUnknown_03000E14 != sub_80870F8)
+ else if (sPlayerKeyInterceptCallback != KeyInterCB_DeferToEventScript)
return FALSE;
temp = sUnknown_03000E18;
- sUnknown_03000E18 = 0;
+ sUnknown_03000E18 = FALSE;
if (temp == TRUE)
return TRUE;
@@ -2824,13 +2887,13 @@ bool32 sub_80875C8(void)
bool32 sub_8087634(void)
{
- if (sub_8087690() < 2)
+ if (GetLinkSendQueueLength() < 2)
return FALSE;
- else if (is_c1_link_related_active() != TRUE)
+ else if (IsUpdateLinkStateCBActive() != TRUE)
return FALSE;
- else if (sub_8009F3C() != TRUE)
+ else if (IsSendingKeysToLink() != TRUE)
return FALSE;
- else if (sUnknown_03000E14 == sub_8087140)
+ else if (sPlayerKeyInterceptCallback == KeyInterCB_DeferToSendQueue)
return TRUE;
else
return FALSE;
@@ -2840,13 +2903,13 @@ bool32 sub_808766C(void)
{
if (gWirelessCommType != 0)
return FALSE;
- else if (!sub_8009F3C())
+ else if (!IsSendingKeysToLink())
return FALSE;
else
return TRUE;
}
-static u32 sub_8087690(void)
+static u32 GetLinkSendQueueLength(void)
{
if (gWirelessCommType != 0)
return gUnknown_03005000.unk_9e8.unk_232;
@@ -2881,7 +2944,7 @@ static void SpawnLinkPlayerEventObject(u8 linkPlayerId, s16 x, s16 y, u8 a4)
linkPlayerEventObj->active = 1;
linkPlayerEventObj->linkPlayerId = linkPlayerId;
linkPlayerEventObj->eventObjId = eventObjId;
- linkPlayerEventObj->mode = 0;
+ linkPlayerEventObj->movementMode = MOVEMENT_MODE_FREE;
eventObj->active = 1;
eventObj->singleMovementActive = a4;
@@ -2923,14 +2986,15 @@ static void sub_808780C(u8 linkPlayerId)
eventObj->active = 0;
}
-static u8 sub_8087858(u8 linkPlayerId)
+// Returns the spriteId corresponding to this player.
+static u8 GetSpriteForLinkedPlayer(u8 linkPlayerId)
{
u8 eventObjId = gLinkPlayerEventObjects[linkPlayerId].eventObjId;
struct EventObject *eventObj = &gEventObjects[eventObjId];
return eventObj->spriteId;
}
-static void sub_8087878(u8 linkPlayerId, u16 *x, u16 *y)
+static void GetLinkPlayerCoords(u8 linkPlayerId, u16 *x, u16 *y)
{
u8 eventObjId = gLinkPlayerEventObjects[linkPlayerId].eventObjId;
struct EventObject *eventObj = &gEventObjects[eventObjId];
@@ -2938,14 +3002,14 @@ static void sub_8087878(u8 linkPlayerId, u16 *x, u16 *y)
*y = eventObj->currentCoords.y;
}
-static u8 sub_80878A0(u8 linkPlayerId)
+static u8 GetLinkPlayerFacingDirection(u8 linkPlayerId)
{
u8 eventObjId = gLinkPlayerEventObjects[linkPlayerId].eventObjId;
struct EventObject *eventObj = &gEventObjects[eventObjId];
return eventObj->range.as_byte;
}
-static u8 sub_80878C0(u8 linkPlayerId)
+static u8 GetLinkPlayerElevation(u8 linkPlayerId)
{
u8 eventObjId = gLinkPlayerEventObjects[linkPlayerId].eventObjId;
struct EventObject *eventObj = &gEventObjects[eventObjId];
@@ -2965,7 +3029,7 @@ static u8 GetLinkPlayerIdAt(s16 x, s16 y)
for (i = 0; i < 4; i++)
{
if (gLinkPlayerEventObjects[i].active
- && (gLinkPlayerEventObjects[i].mode == 0 || gLinkPlayerEventObjects[i].mode == 2))
+ && (gLinkPlayerEventObjects[i].movementMode == 0 || gLinkPlayerEventObjects[i].movementMode == 2))
{
struct EventObject *eventObj = &gEventObjects[gLinkPlayerEventObjects[i].eventObjId];
if (eventObj->currentCoords.x == x && eventObj->currentCoords.y == y)
@@ -2975,7 +3039,7 @@ static u8 GetLinkPlayerIdAt(s16 x, s16 y)
return 4;
}
-static void sub_808796C(u8 linkPlayerId, u8 a2)
+static void SetPlayerFacingDirection(u8 linkPlayerId, u8 facing)
{
struct LinkPlayerEventObject *linkPlayerEventObj = &gLinkPlayerEventObjects[linkPlayerId];
u8 eventObjId = linkPlayerEventObj->eventObjId;
@@ -2983,94 +3047,111 @@ static void sub_808796C(u8 linkPlayerId, u8 a2)
if (linkPlayerEventObj->active)
{
- if (a2 > 10)
+ if (facing > FACING_FORCED_RIGHT)
+ {
eventObj->triggerGroundEffectsOnMove = 1;
+ }
else
- gUnknown_08339E00[gUnknown_08339DC8[linkPlayerEventObj->mode](linkPlayerEventObj, eventObj, a2)](linkPlayerEventObj, eventObj);
+ {
+ // This is a hack to split this code onto two separate lines, without declaring a local variable.
+ // C++ style inline variables would be nice here.
+ #define TEMP gLinkPlayerMovementModes[linkPlayerEventObj->movementMode](linkPlayerEventObj, eventObj, facing)
+
+ gMovementStatusHandler[TEMP](linkPlayerEventObj, eventObj);
+
+ // Clean up the hack.
+ #undef TEMP
+ }
}
}
-static u8 sub_80879D8(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
+
+static u8 MovementEventModeCB_Normal(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
{
- return gUnknown_08339DD4[a3](linkPlayerEventObj, eventObj, a3);
+ return gLinkPlayerFacingHandlers[a3](linkPlayerEventObj, eventObj, a3);
}
-static u8 sub_80879F8(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
+static u8 MovementEventModeCB_Ignored(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
{
- return 1;
+ return FACING_UP;
}
-static u8 sub_80879FC(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
+// Duplicate Function
+static u8 MovementEventModeCB_Normal_2(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
{
- return gUnknown_08339DD4[a3](linkPlayerEventObj, eventObj, a3);
+ return gLinkPlayerFacingHandlers[a3](linkPlayerEventObj, eventObj, a3);
}
-static u8 sub_8087A1C(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
+static bool8 FacingHandler_DoNothing(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
{
- return 0;
+ return FALSE;
}
-static u8 sub_8087A20(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
+static bool8 FacingHandler_DpadMovement(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
{
s16 x, y;
- eventObj->range.as_byte = npc_something3(a3, eventObj->range.as_byte);
+ eventObj->range.as_byte = FlipVerticalAndClearForced(a3, eventObj->range.as_byte);
EventObjectMoveDestCoords(eventObj, eventObj->range.as_byte, &x, &y);
if (LinkPlayerDetectCollision(linkPlayerEventObj->eventObjId, eventObj->range.as_byte, x, y))
{
- return 0;
+ return FALSE;
}
else
{
eventObj->directionSequenceIndex = 16;
ShiftEventObjectCoords(eventObj, x, y);
EventObjectUpdateZCoord(eventObj);
- return 1;
+ return TRUE;
}
}
-static u8 sub_8087A88(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
+static bool8 FacingHandler_ForcedFacingChange(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj, u8 a3)
{
- eventObj->range.as_byte = npc_something3(a3, eventObj->range.as_byte);
- return 0;
+ eventObj->range.as_byte = FlipVerticalAndClearForced(a3, eventObj->range.as_byte);
+ return FALSE;
}
-static void sub_8087AA0(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj)
+// This is called every time a free movement happens. Most of the time it's a No-Op.
+static void MovementStatusHandler_EnterFreeMode(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj)
{
- linkPlayerEventObj->mode = 0;
+ linkPlayerEventObj->movementMode = MOVEMENT_MODE_FREE;
}
-static void sub_8087AA8(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj)
+static void MovementStatusHandler_TryAdvanceScript(struct LinkPlayerEventObject *linkPlayerEventObj, struct EventObject *eventObj)
{
eventObj->directionSequenceIndex--;
- linkPlayerEventObj->mode = 1;
+ linkPlayerEventObj->movementMode = MOVEMENT_MODE_FROZEN;
MoveCoords(eventObj->range.as_byte, &eventObj->initialCoords.x, &eventObj->initialCoords.y);
if (!eventObj->directionSequenceIndex)
{
ShiftStillEventObjectCoords(eventObj);
- linkPlayerEventObj->mode = 2;
+ linkPlayerEventObj->movementMode = MOVEMENT_MODE_SCRIPTED;
}
}
-static u8 npc_something3(u8 a1, u8 a2)
+// Flip Up/Down facing codes. If newFacing doesn't specify a direction, default
+// to oldFacing. Note that this clears also the "FORCED" part of the facing code,
+// even for Left/Right codes.
+static u8 FlipVerticalAndClearForced(u8 newFacing, u8 oldFacing)
{
- switch (a1 - 1)
+ switch (newFacing)
{
- case 0:
- case 6:
- return 2;
- case 1:
- case 7:
- return 1;
- case 2:
- case 8:
- return 3;
- case 3:
- case 9:
- return 4;
+ case FACING_UP:
+ case FACING_FORCED_UP:
+ return DIR_NORTH;
+ case FACING_DOWN:
+ case FACING_FORCED_DOWN:
+ return DIR_SOUTH;
+ case FACING_LEFT:
+ case FACING_FORCED_LEFT:
+ return DIR_WEST;
+ case FACING_RIGHT:
+ case FACING_FORCED_RIGHT:
+ return DIR_EAST;
}
- return a2;
+ return oldFacing;
}
static u8 LinkPlayerDetectCollision(u8 selfEventObjId, u8 a2, s16 x, s16 y)
@@ -3130,7 +3211,7 @@ static void SpriteCB_LinkPlayer(struct Sprite *sprite)
SetObjectSubpriorityByZCoord(eventObj->previousElevation, sprite, 1);
sprite->oam.priority = ZCoordToPriority(eventObj->previousElevation);
- if (!linkPlayerEventObj->mode)
+ if (!linkPlayerEventObj->movementMode != MOVEMENT_MODE_FREE)
StartSpriteAnim(sprite, GetFaceDirectionAnimNum(eventObj->range.as_byte));
else
StartSpriteAnimIfDifferent(sprite, GetMoveDirectionAnimNum(eventObj->range.as_byte));