diff options
Diffstat (limited to 'src/overworld.c')
-rw-r--r-- | src/overworld.c | 3192 |
1 files changed, 3179 insertions, 13 deletions
diff --git a/src/overworld.c b/src/overworld.c index c538595f2..6ee338cb8 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -1,19 +1,3185 @@ - -// Includes #include "global.h" +#include "overworld.h" +#include "main.h" +#include "battle_setup.h" +#include "berry.h" +// #include "cable_club.h" +#include "clock.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_control_avatar.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_ground_effect.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_message_box.h" +#include "field_player_avatar.h" +#include "field_screen_effect.h" +// #include "field_special_scene.h" +#include "field_specials.h" +#include "field_tasks.h" +#include "field_weather.h" +#include "fieldmap.h" +// #include "fldeff_flash.h" +#include "heal_location.h" +#include "link.h" +#include "load_save.h" +#include "main.h" +#include "m4a.h" +#include "constants/maps.h" +#include "map_name_popup.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "new_game.h" +#include "palette.h" +#include "play_time.h" +#include "random.h" +#include "roamer.h" +// #include "rotating_gate.h" +#include "safari_zone.h" +#include "script.h" +// #include "script_pokemon_80C4.h" +#include "secret_base.h" +#include "constants/songs.h" +#include "sound.h" +#include "constants/species.h" +#include "start_menu.h" +#include "task.h" +// #include "tileset_anim.h" +#include "time_events.h" +#include "tv.h" +#include "scanline_effect.h" +#include "wild_encounter.h" +#include "bg.h" +#include "money.h" +#include "save_location.h" +#include "constants/abilities.h" +#include "malloc.h" +#include "gpu_regs.h" +#include "link_rfu.h" + +// 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[]; + +// vars +extern const struct MapData *const gMapAttributes[]; +extern const struct MapHeader *const *const gMapGroups[]; +extern const s32 gMaxFlashLevel; +extern const u16 gUnknown_82EC7C4[]; + +extern u16 gSaveFileStatus; +extern u16 gUnknown_03005DA8; +extern u8 *gUnknown_03005DA0; +extern u8 *gUnknown_03005D9C; +extern u8 *gUnknown_03005DA4; +extern bool8 (*gUnknown_03005DB0)(void); +extern u8 gUnknown_03005DB4; +extern u8 gFieldLinkPlayerCount; +extern MainCallback gFieldCallback; + +// functions +extern void HealPlayerParty(void); +extern void move_tilemap_camera_to_upper_left_corner(void); +extern void cur_mapheader_run_tileset_funcs_after_some_cpuset(void); +extern void DrawWholeMapView(void); +extern void copy_map_tileset1_tileset2_to_vram(const struct MapData *); +extern void apply_map_tileset1_tileset2_palette(const struct MapData *); +extern void ResetCyclingRoadChallengeData(void); +extern void ApplyNewEncryptionKeyToWord(u32 *word, u32 newKey); +extern void mapheader_run_script_with_tag_x5(void); +extern void ResetFieldTasksArgs(void); +extern void sub_80A0A2C(void); +extern void not_trainer_hill_battle_pyramid(void); +extern void apply_map_tileset2_palette(const struct MapData *); +extern void copy_map_tileset2_to_vram_2(const struct MapData *); +extern void prev_quest_postbuffer_cursor_backup_reset(void); +extern void ShowMapNamePopup(void); +extern bool32 InTrainerHill(void); +extern bool32 sub_808651C(void); +extern bool8 sub_80AF6A4(void); +extern bool8 sub_81A9E6C(void); +extern bool8 sub_80E909C(void); +extern void sub_81AA1D8(void); +extern void c2_change_map(void); +extern void sub_81D5DF8(void); +extern void sub_80EB218(void); +extern void sub_81BE72C(void); +extern void sub_80AF3C8(void); +extern void sub_81971F4(void); +extern void sub_808B578(void); +extern void sub_80AF314(void); +extern void sub_80AF214(void); +extern void sub_80AF188(void); +extern void door_upload_tiles(void); +extern void RotatingGate_InitPuzzleAndGraphics(void); +extern void sub_80AF168(void); +extern void sub_80AF3C8(void); +extern void ExecuteTruckSequence(void); +extern void sub_80A0A38(void); +extern void trainer_hill_map_load_related(void); +extern void sub_8087D74(void); +extern void battle_pyramid_map_load_related(u8); +extern void sub_80B00E8(u8); +extern void UpdateTVScreensOnMap(u32, u32); +extern void sub_80E9238(u8); +extern void sub_81A3908(void); +extern void sub_81AA2F8(void); +extern void sub_8195E10(void); +extern void sub_80EDB44(void); +extern void sub_81D64C0(void); +extern void sub_81BE6AC(void); +extern void sub_8098128(void); +extern void copy_map_tileset1_to_vram(const struct MapData *); +extern void copy_map_tileset2_to_vram(const struct MapData *); +extern void FieldUpdateBgTilemapScroll(void); +extern void TransferTilesetAnimsBuffer(void); +extern bool32 sub_81D5F48(void); +extern u8 GetCurrentTrainerHillMapId(void); +extern bool8 warp0_in_pokecenter(void); +extern void dp13_810BB8C(void); +extern void FieldEffectActiveListClear(void); +extern void SetUpFieldTasks(void); +extern void sub_81BE6B8(void); +extern void sub_80AAFA4(void); +extern void sub_809FA9C(void); +extern void sub_80AEE84(void); +extern void mapldr_default(void); +extern void npc_paltag_set_load(u8); +extern void sub_8088B3C(u16, u16); +extern bool32 sub_800F0B8(void); +extern bool32 sub_8009F3C(void); +extern void sub_8010198(void); +extern u32 sub_800B4DC(void); +extern bool32 sub_80B39D4(u8); +extern const u8* sub_809C2C8(struct MapPosition *a1, u8, u8); +extern u8 *sub_809D0F4(void*); +extern u8 sub_808BD6C(u8); +extern u8 sub_808BD7C(u8); +extern void sub_80979D4(struct Sprite*, u8); + +// this file's functions +static void Overworld_ResetStateAfterWhiteOut(void); +static void c2_80567AC(void); +static void CB2_LoadMap2(void); +static void VBlankCB_Field(void); +static void SpriteCB_LinkPlayer(struct Sprite *sprite); +static void ChooseAmbientCrySpecies(void); +static void do_load_map_stuff_loop(u8 *state); +static bool32 map_loading_iteration_3(u8 *state); +static bool32 sub_8086638(u8 *state); +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 map_loading_lcd_reset(void); +static u8 sub_8087858(u8); +static u16 sub_80871C0(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 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 u8 LinkPlayerDetectCollision(u8 selfMapObjId, 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 s32 sub_80878E4(u8 linkPlayerId); +static u8 GetLinkPlayerIdAt(s16 x, s16 y); +static void sub_808796C(u8 linkPlayerId, u8 a2); +static void ZeroMapObject(struct MapObject *mapObj); +static void SpawnLinkPlayerMapObject(u8 linkPlayerId, s16 x, s16 y, u8 a4); +static void InitLinkPlayerMapObjectPos(struct MapObject *mapObj, 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 void sub_8087584(void); +static u32 sub_8087690(void); +static void ZeroLinkPlayerMapObject(struct LinkPlayerMapObject *linkPlayerMapObj); +static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1); +static u16 sub_8087480(const u8 *script); +static void sub_8087510(void); +static void sub_808751C(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 SetFieldVBlankCallback(void); +static void FieldClearVBlankHBlankCallbacks(void); +static void sub_8085810(void); +static u8 sub_808532C(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3); +static u8 sub_808538C(struct UnkPlayerStruct *playerStruct, u8 a2, u16 a3, u8 a4); +static u16 cur_mapdata_block_role_at_screen_center_acc_to_sav1(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 u32 sUnusedVar; + +// EWRAM vars +EWRAM_DATA static u8 sUnknown_020322D8 = 0; +EWRAM_DATA struct WarpData gUnknown_020322DC = {0}; +EWRAM_DATA static struct WarpData sWarpDestination = {0}; // new warp position +EWRAM_DATA static struct WarpData sUnknown_020322EC = {0}; +EWRAM_DATA static struct WarpData sUnknown_020322F4 = {0}; +EWRAM_DATA static u16 sLastMapSectionId = 0; +EWRAM_DATA static struct UnkPlayerStruct sUnknown_02032300 = {0}; +EWRAM_DATA static u16 sAmbientCrySpecies = 0; +EWRAM_DATA static bool8 sIsAmbientCryWaterMon = FALSE; +EWRAM_DATA struct LinkPlayerMapObject gLinkPlayerMapObjects[4] = {0}; + +// const rom data +static const struct WarpData sDummyWarpData = +{ + .mapGroup = -1, + .mapNum = -1, + .warpId = -1, + .x = -1, + .y = -1, +}; + +static const u8 sUnusedData[] = +{ + 0xB0, 0x04, 0x00, 0x00, + 0x10, 0x0E, 0x00, 0x00, + 0xB0, 0x04, 0x00, 0x00, + 0x60, 0x09, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, + 0xD4, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x00, 0x00, +}; + +const struct UCoords32 gUnknown_08339D64[] = +{ + { 0, 0}, + { 0, 1}, + { 0, -1}, + {-1, 0}, + { 1, 0}, + {-1, 1}, + { 1, 1}, + {-1, -1}, + { 1, -1}, +}; + +static const struct BgTemplate gUnknown_08339DAC[] = +{ + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 29, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + }, + { + .bg = 2, + .charBaseIndex = 0, + .mapBaseIndex = 28, + .screenSize = 0, + .paletteMode = 0, + .priority = 2, + .baseTile = 0 + }, + { + .bg = 3, + .charBaseIndex = 0, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0 + } +}; + +static const struct ScanlineEffectParams gUnknown_08339DBC = +{ + (void *)REG_ADDR_WIN0H, + ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1, + 1, + 0, +}; + +static u8 sub_80879D8(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_80879F8(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_80879FC(struct LinkPlayerMapObject *, struct MapObject *, u8); + +static u8 (*const gUnknown_08339DC8[])(struct LinkPlayerMapObject *, struct MapObject *, u8) = +{ + sub_80879D8, + sub_80879F8, + sub_80879FC, +}; + +static u8 sub_8087A1C(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8087A20(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8087A88(struct LinkPlayerMapObject *, struct MapObject *, u8); + +static u8 (*const gUnknown_08339DD4[])(struct LinkPlayerMapObject *, struct MapObject *, u8) = +{ + sub_8087A1C, + sub_8087A20, + sub_8087A20, + sub_8087A20, + sub_8087A20, + sub_8087A1C, + sub_8087A1C, + sub_8087A88, + sub_8087A88, + sub_8087A88, + sub_8087A88, +}; + +static void sub_8087AA0(struct LinkPlayerMapObject *, struct MapObject *); +static void sub_8087AA8(struct LinkPlayerMapObject *, struct MapObject *); + +static void (*const gUnknown_08339E00[])(struct LinkPlayerMapObject *, struct MapObject *) = +{ + sub_8087AA0, + sub_8087AA8, +}; + +// code +void DoWhiteOut(void) +{ + ScriptContext2_RunNewScript(EventScript_WhiteOut); + SetMoney(&gSaveBlock1Ptr->money, GetMoney(&gSaveBlock1Ptr->money) / 2); + HealPlayerParty(); + Overworld_ResetStateAfterWhiteOut(); + Overworld_SetWarpDestToLastHealLoc(); + warp_in(); +} + +void Overworld_ResetStateAfterFly(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); +} + +void Overworld_ResetStateAfterTeleport(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); + ScriptContext2_RunNewScript(EventScript_271862); +} + +void Overworld_ResetStateAfterDigEscRope(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); +} + +static void Overworld_ResetStateAfterWhiteOut(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); + if (VarGet(VAR_0x4039) == 1) + { + VarSet(VAR_0x4039, 0); + VarSet(VAR_0x4037, 0); + } +} + +static void sub_8084788(void) +{ + FlagClear(FLAG_SYS_SAFARI_MODE); + ChooseAmbientCrySpecies(); + ResetCyclingRoadChallengeData(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); +} + +void ResetGameStats(void) +{ + s32 i; + + for (i = 0; i < NUM_GAME_STATS; i++) + SetGameStat(i, 0); +} + +void IncrementGameStat(u8 index) +{ + if (index < NUM_USED_GAME_STATS) + { + u32 statVal = GetGameStat(index); + if (statVal < 0xFFFFFF) + statVal++; + else + statVal = 0xFFFFFF; + + SetGameStat(index, statVal); + } +} + +u32 GetGameStat(u8 index) +{ + if (index >= NUM_USED_GAME_STATS) + return 0; + + return gSaveBlock1Ptr->gameStats[index] ^ gSaveBlock2Ptr->encryptionKey; +} + +void SetGameStat(u8 index, u32 value) +{ + if (index < NUM_USED_GAME_STATS) + gSaveBlock1Ptr->gameStats[index] = value ^ gSaveBlock2Ptr->encryptionKey; +} + +void ApplyNewEncryptionKeyToGameStats(u32 newKey) +{ + u8 i; + + for (i = 0; i < NUM_GAME_STATS; i++) + ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->gameStats[i], newKey); +} + +void LoadMapObjTemplatesFromHeader(void) +{ + // Clear map object templates + CpuFill32(0, gSaveBlock1Ptr->mapObjectTemplates, sizeof(gSaveBlock1Ptr->mapObjectTemplates)); + + // Copy map header events to save block + CpuCopy32(gMapHeader.events->mapObjects, + gSaveBlock1Ptr->mapObjectTemplates, + gMapHeader.events->mapObjectCount * sizeof(struct MapObjectTemplate)); +} + +void LoadSaveblockMapObjScripts(void) +{ + struct MapObjectTemplate *mapHeaderObjTemplates = gMapHeader.events->mapObjects; + struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates; + s32 i; + + for (i = 0; i < 64; i++) + savObjTemplates[i].script = mapHeaderObjTemplates[i].script; +} + +void Overworld_SetMapObjTemplateCoords(u8 localId, s16 x, s16 y) +{ + s32 i; + struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates; + + for (i = 0; i < 64; i++) + { + struct MapObjectTemplate *mapObjectTemplate = &savObjTemplates[i]; + if (mapObjectTemplate->localId == localId) + { + mapObjectTemplate->x = x; + mapObjectTemplate->y = y; + return; + } + } +} + +void Overworld_SetMapObjTemplateMovementType(u8 localId, u8 movementType) +{ + s32 i; + + struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates; + for (i = 0; i < 64; i++) + { + struct MapObjectTemplate *mapObjectTemplate = &savObjTemplates[i]; + if (mapObjectTemplate->localId == localId) + { + mapObjectTemplate->movementType = movementType; + return; + } + } +} + +static void mapdata_load_assets_to_gpu_and_full_redraw(void) +{ + move_tilemap_camera_to_upper_left_corner(); + copy_map_tileset1_tileset2_to_vram(gMapHeader.mapData); + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + DrawWholeMapView(); + cur_mapheader_run_tileset_funcs_after_some_cpuset(); +} + +const struct MapData *get_mapdata_header(void) +{ + u16 mapDataId = gSaveBlock1Ptr->mapDataId; + if (mapDataId) + return gMapAttributes[mapDataId - 1]; + return NULL; +} + +void ApplyCurrentWarp(void) +{ + gUnknown_020322DC = gSaveBlock1Ptr->location; + gSaveBlock1Ptr->location = sWarpDestination; + sUnknown_020322EC = sDummyWarpData; + sUnknown_020322F4 = sDummyWarpData; +} + +void set_warp2_warp3_to_neg_1(void) +{ + sUnknown_020322EC = sDummyWarpData; + sUnknown_020322F4 = sDummyWarpData; +} + +void SetWarpData(struct WarpData *warp, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + warp->mapGroup = mapGroup; + warp->mapNum = mapNum; + warp->warpId = warpId; + warp->x = x; + warp->y = y; +} + +bool32 warp_data_is_not_neg_1(struct WarpData *warp) +{ + if (warp->mapGroup != -1) + return FALSE; + else if (warp->mapNum != -1) + return FALSE; + else if (warp->warpId != -1) + return FALSE; + else if (warp->x != -1) + return FALSE; + else if (warp->y != -1) + return FALSE; + else + return TRUE; +} + +const struct MapHeader *Overworld_GetMapHeaderByGroupAndId(u16 mapGroup, u16 mapNum) +{ + return gMapGroups[mapGroup][mapNum]; +} + +const struct MapHeader *warp1_get_mapheader(void) +{ + return Overworld_GetMapHeaderByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); +} + +void set_current_map_header_from_sav1_save_old_name(void) +{ + sLastMapSectionId = gMapHeader.regionMapSectionId; + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gSaveBlock1Ptr->mapDataId = gMapHeader.mapDataId; + gMapHeader.mapData = get_mapdata_header(); +} + +void LoadSaveblockMapHeader(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gMapHeader.mapData = get_mapdata_header(); +} + +void update_camera_pos_from_warpid(void) +{ + if (gSaveBlock1Ptr->location.warpId >= 0 && gSaveBlock1Ptr->location.warpId < gMapHeader.events->warpCount) + { + gSaveBlock1Ptr->pos.x = gMapHeader.events->warps[gSaveBlock1Ptr->location.warpId].x; + gSaveBlock1Ptr->pos.y = gMapHeader.events->warps[gSaveBlock1Ptr->location.warpId].y; + } + else if (gSaveBlock1Ptr->location.x >= 0 && gSaveBlock1Ptr->location.y >= 0) + { + gSaveBlock1Ptr->pos.x = gSaveBlock1Ptr->location.x; + gSaveBlock1Ptr->pos.y = gSaveBlock1Ptr->location.y; + } + else + { + gSaveBlock1Ptr->pos.x = gMapHeader.mapData->width / 2; + gSaveBlock1Ptr->pos.y = gMapHeader.mapData->height / 2; + } +} + +void warp_in(void) +{ + ApplyCurrentWarp(); + set_current_map_header_from_sav1_save_old_name(); + update_camera_pos_from_warpid(); +} + +void Overworld_SetWarpDestination(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sWarpDestination, mapGroup, mapNum, warpId, x, y); +} + +void warp1_set_2(s8 mapGroup, s8 mapNum, s8 warpId) +{ + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, -1, -1); +} + +void saved_warp2_set(s32 unused, s8 mapGroup, s8 mapNum, s8 warpId) +{ + SetWarpData(&gSaveBlock1Ptr->warp2, mapGroup, mapNum, warpId, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y); +} + +void saved_warp2_set_2(s32 unused, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->warp2, mapGroup, mapNum, warpId, x, y); +} + +void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused) +{ + sWarpDestination = gSaveBlock1Ptr->warp2; +} + +void sub_8084CCC(u8 a1) +{ + const struct HealLocation *warp = GetHealLocationPointer(a1); + + if (warp) + Overworld_SetWarpDestination(warp->group, warp->map, -1, warp->x, warp->y); +} + +void Overworld_SetWarpDestToLastHealLoc(void) +{ + sWarpDestination = gSaveBlock1Ptr->lastHealLocation; +} + +void Overworld_SetHealLocationWarp(u8 healLocationId) +{ + const struct HealLocation *healLocation = GetHealLocationPointer(healLocationId); + + if (healLocation != NULL) + SetWarpData(&gSaveBlock1Ptr->lastHealLocation, healLocation->group, healLocation->map, -1, healLocation->x, healLocation->y); +} + +void sub_8084D5C(s16 a1, s16 a2) +{ + u8 currMapType = Overworld_GetMapTypeOfSaveblockLocation(); + u8 destMapType = GetMapTypeByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); + if (is_light_level_1_2_3_5_or_6(currMapType) && is_light_level_1_2_3_5_or_6(destMapType) != TRUE) + sub_8084DD4(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, a1 - 7, a2 - 6); +} + +void sub_8084DD4(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->warp4, mapGroup, mapNum, warpId, x, y); +} + +void sub_8084E14(void) +{ + sWarpDestination = gSaveBlock1Ptr->warp4; +} + +void sub_8084E2C(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sUnknown_020322EC, mapGroup, mapNum, warpId, x, y); +} + +void warp1_set_to_warp2(void) +{ + sWarpDestination = sUnknown_020322EC; +} + +void sub_8084E80(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sUnknown_020322F4, mapGroup, mapNum, warpId, x, y); +} + +void sub_8084EBC(s16 x, s16 y) +{ + if (warp_data_is_not_neg_1(&sUnknown_020322F4) == TRUE) + sWarpDestination = gUnknown_020322DC; + else + Overworld_SetWarpDestination(sUnknown_020322F4.mapGroup, sUnknown_020322F4.mapNum, -1, x, y); +} + +void warp1_set_to_sav1w(void) +{ + sWarpDestination = gSaveBlock1Ptr->warp1; +} + +void sub_8084F2C(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->warp1, mapGroup, mapNum, warpId, x, y); +} + +void sub_8084F6C(u8 a1) +{ + const struct HealLocation *warp = GetHealLocationPointer(a1); + if (warp) + SetWarpData(&gSaveBlock1Ptr->warp1, warp->group, warp->map, -1, warp->x, warp->y); +} + +void sub_8084FAC(void) +{ + gSaveBlock1Ptr->warp1 = gSaveBlock1Ptr->warp2; +} + +const struct MapConnection *GetMapConnection(u8 dir) +{ + s32 i; + s32 count = gMapHeader.connections->count; + const struct MapConnection *connection = gMapHeader.connections->connections; + + if (connection == NULL) + return NULL; + + for(i = 0; i < count; i++, connection++) + if (connection->direction == dir) + return connection; + + return NULL; +} + +bool8 sub_8084FF8(u8 dir, u16 x, u16 y) +{ + const struct MapConnection *connection = GetMapConnection(dir); + + if (connection != NULL) + { + Overworld_SetWarpDestination(connection->mapGroup, connection->mapNum, -1, x, y); + } + else + { + mapheader_run_script_with_tag_x6(); + if (warp_data_is_not_neg_1(&sUnknown_020322EC)) + return FALSE; + warp1_set_to_warp2(); + } + return TRUE; +} + +bool8 sub_8085058(u16 x, u16 y) +{ + return sub_8084FF8(CONNECTION_EMERGE, x, y); +} + +bool8 sub_8085078(u16 x, u16 y) +{ + return sub_8084FF8(CONNECTION_DIVE, x, y); +} + +void mliX_load_map(u8 mapGroup, u8 mapNum) +{ + s32 paletteIndex; + + Overworld_SetWarpDestination(mapGroup, mapNum, -1, -1, -1); + if (gMapHeader.regionMapSectionId != 0x3A) + sub_8085810(); + + ApplyCurrentWarp(); + set_current_map_header_from_sav1_save_old_name(); + LoadMapObjTemplatesFromHeader(); + TrySetMapSaveWarpStatus(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + prev_quest_postbuffer_cursor_backup_reset(); + TryUpdateRandomTrainerRematches(mapGroup, mapNum); + DoTimeBasedEvents(); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + mapheader_run_script_with_tag_x3(); + not_trainer_hill_battle_pyramid(); + copy_map_tileset2_to_vram_2(gMapHeader.mapData); + apply_map_tileset2_palette(gMapHeader.mapData); + + for (paletteIndex = 6; paletteIndex < 13; paletteIndex++) + ApplyWeatherGammaShiftToPal(paletteIndex); + + sub_80A0A2C(); + UpdateLocationHistoryForRoamer(); + RoamerMove(); + DoCurrentWeather(); + ResetFieldTasksArgs(); + mapheader_run_script_with_tag_x5(); + + if (gMapHeader.regionMapSectionId != 0x3A || gMapHeader.regionMapSectionId != sLastMapSectionId) + ShowMapNamePopup(); +} + +static void mli0_load_map(u32 a1) +{ + bool8 v2; + bool8 indoors; + + set_current_map_header_from_sav1_save_old_name(); + if (!(sUnknown_020322D8 & 1)) + { + if (gMapHeader.mapDataId == 0x169) + sub_81AA1D8(); + else if (InTrainerHill()) + sub_81D5DF8(); + else + LoadMapObjTemplatesFromHeader(); + } + + v2 = is_light_level_1_2_3_5_or_6(gMapHeader.mapType); + indoors = Overworld_MapTypeIsIndoors(gMapHeader.mapType); + + sub_80EB218(); + TrySetMapSaveWarpStatus(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + prev_quest_postbuffer_cursor_backup_reset(); + TryUpdateRandomTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + if (a1 != 1) + DoTimeBasedEvents(); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + if (v2) + FlagClear(FLAG_SYS_USE_FLASH); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + mapheader_run_script_with_tag_x3(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); + if (gMapHeader.mapDataId == 0x169) + battle_pyramid_map_load_related(0); + else if (InTrainerHill()) + trainer_hill_map_load_related(); + else + not_trainer_hill_battle_pyramid(); + + if (a1 != 1 && indoors) + { + UpdateTVScreensOnMap(gUnknown_03005DC0.width, gUnknown_03005DC0.height); + sub_80E9238(1); + } +} + +void player_avatar_init_params_reset(void) +{ + sUnknown_02032300.player_field_1 = 1; + sUnknown_02032300.player_field_0 = 1; +} + +void walkrun_find_lowest_active_bit_in_bitfield(void) +{ + sUnknown_02032300.player_field_1 = player_get_direction_lower_nybble(); + + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE)) + sUnknown_02032300.player_field_0 = 2; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_ACRO_BIKE)) + sUnknown_02032300.player_field_0 = 4; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + sUnknown_02032300.player_field_0 = 8; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_4)) + sUnknown_02032300.player_field_0 = 16; + else + sUnknown_02032300.player_field_0 = 1; +} + +static struct UnkPlayerStruct *sub_80852D4(void) +{ + struct UnkPlayerStruct playerStruct; + u8 mapType = Overworld_GetMapTypeOfSaveblockLocation(); + u16 v2 = cur_mapdata_block_role_at_screen_center_acc_to_sav1(); + u8 v4 = sub_808532C(&sUnknown_02032300, v2, mapType); + playerStruct.player_field_0 = v4; + playerStruct.player_field_1 = sub_808538C(&sUnknown_02032300, v4, v2, mapType); + sUnknown_02032300 = playerStruct; + return &sUnknown_02032300; +} + +static u8 sub_808532C(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3) +{ + if (a3 != 8 && FlagGet(FLAG_SYS_CRUISE_MODE)) + return 1; + else if (a3 == 5) + return 16; + else if (MetatileBehavior_IsSurfableWaterOrUnderwater(a2) == 1) + return 8; + else if (Overworld_IsBikingAllowed() != TRUE) + return 1; + else if (playerStruct->player_field_0 == 2) + return 2; + else if (playerStruct->player_field_0 != 4) + return 1; + else + return 4; +} + +static u8 sub_808538C(struct UnkPlayerStruct *playerStruct, u8 a2, u16 a3, u8 a4) +{ + if (FlagGet(FLAG_SYS_CRUISE_MODE) && a4 == 6) + return 4; + else if (MetatileBehavior_IsDeepSouthWarp(a3) == TRUE) + return 2; + else if (MetatileBehavior_IsNonAnimDoor(a3) == TRUE || MetatileBehavior_IsDoor(a3) == TRUE) + return 1; + else if (MetatileBehavior_IsSouthArrowWarp(a3) == TRUE) + return 2; + else if (MetatileBehavior_IsNorthArrowWarp(a3) == TRUE) + return 1; + else if (MetatileBehavior_IsWestArrowWarp(a3) == TRUE) + return 4; + else if (MetatileBehavior_IsEastArrowWarp(a3) == TRUE) + return 3; + else if ((playerStruct->player_field_0 == 16 && a2 == 8) + || (playerStruct->player_field_0 == 8 && a2 == 16)) + return playerStruct->player_field_1; + else if (MetatileBehavior_IsLadder(a3) == TRUE) + return playerStruct->player_field_1; + else + return 1; +} + +static u16 cur_mapdata_block_role_at_screen_center_acc_to_sav1(void) +{ + return MapGridGetMetatileBehaviorAt(gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7); +} + +bool32 Overworld_IsBikingAllowed(void) +{ + if (!(gMapHeader.flags & 1)) + return FALSE; + else + return TRUE; +} + +void SetDefaultFlashLevel(void) +{ + if (!gMapHeader.cave) + gSaveBlock1Ptr->flashLevel = 0; + else if (FlagGet(FLAG_SYS_USE_FLASH)) + gSaveBlock1Ptr->flashLevel = 1; + else + gSaveBlock1Ptr->flashLevel = gMaxFlashLevel - 1; +} + +void Overworld_SetFlashLevel(s32 flashLevel) +{ + if (flashLevel < 0 || flashLevel > gMaxFlashLevel) + flashLevel = 0; + gSaveBlock1Ptr->flashLevel = flashLevel; +} + +u8 Overworld_GetFlashLevel(void) +{ + return gSaveBlock1Ptr->flashLevel; +} + +void sub_8085524(u16 mapDataId) +{ + gSaveBlock1Ptr->mapDataId = mapDataId; + gMapHeader.mapData = get_mapdata_header(); +} + +void sub_8085540(u8 var) +{ + sUnknown_020322D8 = var; +} + +u8 sub_808554C(void) +{ + return sUnknown_020322D8; +} + +static bool16 ShouldLegendaryMusicPlayAtLocation(struct WarpData *warp) +{ + if (!FlagGet(FLAG_SYS_WEATHER_CTRL)) + return FALSE; + if (warp->mapGroup == 0) + { + switch (warp->mapNum) + { + case MAP_NUM(LILYCOVE_CITY): + case MAP_NUM(MOSSDEEP_CITY): + case MAP_NUM(SOOTOPOLIS_CITY): + case MAP_NUM(EVER_GRANDE_CITY): + case MAP_NUM(ROUTE124): + case MAP_NUM(ROUTE125): + case MAP_NUM(ROUTE126): + case MAP_NUM(ROUTE127): + case MAP_NUM(ROUTE128): + return TRUE; + default: + if (VarGet(VAR_0x405E) < 4) + return FALSE; + switch (warp->mapNum) + { + case MAP_NUM(ROUTE129): + case MAP_NUM(ROUTE130): + case MAP_NUM(ROUTE131): + return TRUE; + } + } + } + return FALSE; +} + +static bool16 NoMusicInSotopolisWithLegendaries(struct WarpData *warp) +{ + if (VarGet(VAR_0x40CA) != 1) + return FALSE; + else if (warp->mapGroup != MAP_GROUP(SOOTOPOLIS_CITY)) + return FALSE; + else if (warp->mapNum == MAP_NUM(SOOTOPOLIS_CITY)) + return TRUE; + else + return FALSE; +} + +static bool16 IsInfiltratedWeatherInstitute(struct WarpData *warp) +{ + if (VarGet(VAR_WEATHER_INSTITUTE_STATE)) + return FALSE; + else if (warp->mapGroup != MAP_GROUP(ROUTE119_WEATHER_INSTITUTE_1F)) + return FALSE; + else if (warp->mapNum == MAP_NUM(ROUTE119_WEATHER_INSTITUTE_1F) + || warp->mapNum == MAP_NUM(ROUTE119_WEATHER_INSTITUTE_2F)) + return TRUE; + else + return FALSE; +} + +static bool16 IsInflitratedSpaceCenter(struct WarpData *warp) +{ + if (VarGet(VAR_0x405D) == 0) + return FALSE; + else if (VarGet(VAR_0x405D) > 2) + return FALSE; + else if (warp->mapGroup != MAP_GROUP(MOSSDEEP_CITY_SPACE_CENTER_1F)) + return FALSE; + else if (warp->mapNum == MAP_NUM(MOSSDEEP_CITY_SPACE_CENTER_1F) + || warp->mapNum == MAP_NUM(MOSSDEEP_CITY_SPACE_CENTER_2F)) + return TRUE; + return FALSE; +} + +u16 GetLocationMusic(struct WarpData *warp) +{ + if (NoMusicInSotopolisWithLegendaries(warp) == TRUE) + return 0xFFFF; + else if (ShouldLegendaryMusicPlayAtLocation(warp) == TRUE) + return MUS_OOAME; + else if (IsInflitratedSpaceCenter(warp) == TRUE) + return MUS_MGM0; + else if (IsInfiltratedWeatherInstitute(warp) == TRUE) + return MUS_TOZAN; + else + return Overworld_GetMapHeaderByGroupAndId(warp->mapGroup, warp->mapNum)->music; +} + +u16 GetCurrLocationDefaultMusic(void) +{ + u16 music; + + // Play the desert music only when the sandstorm is active on Route 111. + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE111) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE111) + && GetSav1Weather() == 8) + return MUS_ASHROAD; + + music = GetLocationMusic(&gSaveBlock1Ptr->location); + if (music != 0x7FFF) + { + return music; + } + else + { + if (gSaveBlock1Ptr->pos.x < 24) + return MUS_DOORO_X1; + else + return MUS_GRANROAD; + } +} + +u16 GetWarpDestinationMusic(void) +{ + u16 music = GetLocationMusic(&sWarpDestination); + if (music != 0x7FFF) + { + return music; + } + else + { + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(MAUVILLE_CITY) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(MAUVILLE_CITY)) + return MUS_DOORO_X1; + else + return MUS_GRANROAD; + } +} + +void Overworld_ResetMapMusic(void) +{ + ResetMapMusic(); +} + +void Overworld_PlaySpecialMapMusic(void) +{ + u16 music = GetCurrLocationDefaultMusic(); + + if (music != MUS_OOAME && music != 0xFFFF) + { + if (gSaveBlock1Ptr->savedMusic) + music = gSaveBlock1Ptr->savedMusic; + else if (Overworld_GetMapTypeOfSaveblockLocation() == MAP_TYPE_UNDERWATER) + music = MUS_DEEPDEEP; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + music = MUS_NAMINORI; + } + + if (music != GetCurrentMapMusic()) + PlayNewMapMusic(music); +} + +void Overworld_SetSavedMusic(u16 songNum) +{ + gSaveBlock1Ptr->savedMusic = songNum; +} + +void Overworld_ClearSavedMusic(void) +{ + gSaveBlock1Ptr->savedMusic = 0; +} + +static void sub_8085810(void) +{ + if (FlagGet(FLAG_SPECIAL_FLAG_0x4001) != TRUE) + { + u16 newMusic = GetWarpDestinationMusic(); + u16 currentMusic = GetCurrentMapMusic(); + if (newMusic != MUS_OOAME && newMusic != 0xFFFF) + { + if (currentMusic == MUS_DEEPDEEP || currentMusic == MUS_NAMINORI) + return; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + newMusic = MUS_NAMINORI; + } + if (newMusic != currentMusic) + { + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) + FadeOutAndFadeInNewMapMusic(newMusic, 4, 4); + else + FadeOutAndPlayNewMapMusic(newMusic, 8); + } + } +} + +void Overworld_ChangeMusicToDefault(void) +{ + u16 currentMusic = GetCurrentMapMusic(); + if (currentMusic != GetCurrLocationDefaultMusic()) + FadeOutAndPlayNewMapMusic(GetCurrLocationDefaultMusic(), 8); +} + +void Overworld_ChangeMusicTo(u16 newMusic) +{ + u16 currentMusic = GetCurrentMapMusic(); + if (currentMusic != newMusic && currentMusic != MUS_OOAME) + FadeOutAndPlayNewMapMusic(newMusic, 8); +} + +u8 GetMapMusicFadeoutSpeed(void) +{ + const struct MapHeader *mapHeader = warp1_get_mapheader(); + if (Overworld_MapTypeIsIndoors(mapHeader->mapType) == TRUE) + return 2; + else + return 4; +} + +void music_something(void) +{ + u16 currentMusic = GetCurrentMapMusic(); + u16 warpMusic = GetWarpDestinationMusic(); + if (FlagGet(FLAG_SPECIAL_FLAG_0x4001) != TRUE && warpMusic != GetCurrentMapMusic()) + { + if (currentMusic == MUS_NAMINORI + && VarGet(VAR_0x40CA) == 2 + && gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(SOOTOPOLIS_CITY) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(SOOTOPOLIS_CITY) + && sWarpDestination.mapGroup == MAP_GROUP(SOOTOPOLIS_CITY) + && sWarpDestination.mapNum == MAP_NUM(SOOTOPOLIS_CITY) + && sWarpDestination.x == 0x1D + && sWarpDestination.y == 0x35) + return; + FadeOutMapMusic(GetMapMusicFadeoutSpeed()); + } +} + +bool8 sub_80859A0(void) +{ + return IsNotWaitingForBGMStop(); +} + +void Overworld_FadeOutMapMusic(void) +{ + FadeOutMapMusic(4); +} + +static void PlayAmbientCry(void) +{ + s16 x, y; + s8 pan; + s8 volume; + + PlayerGetDestCoords(&x, &y); + if (sIsAmbientCryWaterMon == TRUE + && !MetatileBehavior_IsSurfableWaterOrUnderwater(MapGridGetMetatileBehaviorAt(x, y))) + return; + pan = (Random() % 88) + 212; + volume = (Random() % 30) + 50; + PlayCry2(sAmbientCrySpecies, pan, volume, 1); +} + +void UpdateAmbientCry(s16 *state, u16 *delayCounter) +{ + u8 i, monsCount, divBy; + + switch (*state) + { + case 0: + if (sAmbientCrySpecies == SPECIES_NONE) + *state = 4; + else + *state = 1; + break; + case 1: + *delayCounter = (Random() % 2400) + 1200; + *state = 3; + break; + case 2: + divBy = 1; + monsCount = CalculatePlayerPartyCount(); + for (i = 0; i < monsCount; i++) + { + if (!GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT3) + && GetMonAbility(&gPlayerParty[0]) == ABILITY_SWARM) + { + divBy = 2; + break; + } + } + *delayCounter = ((Random() % 1200) + 1200) / divBy; + *state = 3; + break; + case 3: + (*delayCounter)--; + if (*delayCounter == 0) + { + PlayAmbientCry(); + *state = 2; + } + break; + case 4: + break; + } +} + +static void ChooseAmbientCrySpecies(void) +{ + if ((gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE130) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE130)) + && !IsMirageIslandPresent()) + { + // Only play water pokemon cries on this route + // when Mirage Island is not present + sIsAmbientCryWaterMon = TRUE; + sAmbientCrySpecies = GetLocalWaterMon(); + } + else + { + sAmbientCrySpecies = GetLocalWildMon(&sIsAmbientCryWaterMon); + } +} + +u8 GetMapTypeByGroupAndId(s8 mapGroup, s8 mapNum) +{ + return Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum)->mapType; +} + +u8 GetMapTypeByWarpData(struct WarpData *warp) +{ + return GetMapTypeByGroupAndId(warp->mapGroup, warp->mapNum); +} + +u8 Overworld_GetMapTypeOfSaveblockLocation(void) +{ + return GetMapTypeByWarpData(&gSaveBlock1Ptr->location); +} + +u8 get_map_light_from_warp0(void) +{ + return GetMapTypeByWarpData(&gUnknown_020322DC); +} + +bool8 is_light_level_1_2_3_5_or_6(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_UNDERWATER + || mapType == MAP_TYPE_CITY + || mapType == MAP_TYPE_6) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeAllowsTeleportAndFly(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_6 + || mapType == MAP_TYPE_CITY) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeIsIndoors(u8 mapType) +{ + if (mapType == MAP_TYPE_INDOOR + || mapType == MAP_TYPE_SECRET_BASE) + return TRUE; + else + return FALSE; +} + +u8 sav1_saved_warp2_map_get_name(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->warp2.mapGroup, gSaveBlock1Ptr->warp2.mapNum)->regionMapSectionId; +} + +u8 sav1_map_get_name(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)->regionMapSectionId; +} + +u8 GetCurrentMapBattleScene(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)->battleType; +} + +static void overworld_bg_setup(void) +{ + InitBgsFromTemplates(0, gUnknown_08339DAC, ARRAY_COUNT(gUnknown_08339DAC)); + SetBgAttribute(1, BG_CTRL_ATTR_PALETTEMODE, 1); + SetBgAttribute(2, BG_CTRL_ATTR_PALETTEMODE, 1); + SetBgAttribute(3, BG_CTRL_ATTR_PALETTEMODE, 1); + gUnknown_03005DA0 = AllocZeroed(0x800); + gUnknown_03005D9C = AllocZeroed(0x800); + gUnknown_03005DA4 = AllocZeroed(0x800); + SetBgTilemapBuffer(1, gUnknown_03005DA0); + SetBgTilemapBuffer(2, gUnknown_03005D9C); + SetBgTilemapBuffer(3, gUnknown_03005DA4); + sub_81971D0(); +} + +void overworld_free_bg_tilemaps(void) +{ + sub_81BE72C(); + sub_81971F4(); + if (gUnknown_03005DA4 != NULL) + FREE_AND_SET_NULL(gUnknown_03005DA4); + if (gUnknown_03005D9C != NULL) + FREE_AND_SET_NULL(gUnknown_03005D9C); + if (gUnknown_03005DA0 != NULL) + FREE_AND_SET_NULL(gUnknown_03005DA0); +} + +static void ResetSafariZoneFlag_(void) +{ + ResetSafariZoneFlag(); +} + +bool32 is_c1_link_related_active(void) +{ + if (gMain.callback1 == c1_link_related) + return TRUE; + else + return FALSE; +} + +static void DoCB1_Overworld(u16 newKeys, u16 heldKeys) +{ + struct FieldInput inputStruct; + + sub_808B578(); + FieldClearPlayerInput(&inputStruct); + FieldGetPlayerInput(&inputStruct, newKeys, heldKeys); + if (!ScriptContext2_IsEnabled()) + { + if (sub_809C014(&inputStruct) == 1) + { + ScriptContext2_Enable(); + HideMapNamePopUpWindow(); + } + else + { + player_step(inputStruct.dpadDirection, newKeys, heldKeys); + } + } +} + +void CB1_Overworld(void) +{ + if (gMain.callback2 == CB2_Overworld) + DoCB1_Overworld(gMain.newKeys, gMain.heldKeys); +} + +static void OverworldBasic(void) +{ + ScriptContext2_RunScript(); + RunTasks(); + AnimateSprites(); + CameraUpdate(); + UpdateCameraPanning(); + BuildOamBuffer(); + UpdatePaletteFade(); + sub_80A0A38(); + do_scheduled_bg_tilemap_copies_to_vram(); +} + +// This CB2 is used when starting +void CB2_OverworldBasic(void) +{ + OverworldBasic(); +} + +void CB2_Overworld(void) +{ + bool32 fading = (gPaletteFade.active != 0); + if (fading) + SetVBlankCallback(NULL); + OverworldBasic(); + if (fading) + SetFieldVBlankCallback(); +} + +void SetMainCallback1(MainCallback cb) +{ + gMain.callback1 = cb; +} + +void sub_8085E94(void *a0) +{ + sUnknown_03000E0C = a0; +} + +static bool8 map_post_load_hook_exec(void) +{ + if (gUnknown_03005DB0 != NULL) + { + if (!gUnknown_03005DB0()) + { + return FALSE; + } + else + { + gUnknown_03005DB0 = NULL; + gFieldCallback = NULL; + } + } + else + { + if (gFieldCallback != NULL) + gFieldCallback(); + else + mapldr_default(); + + gFieldCallback = NULL; + } + + return TRUE; +} + +void CB2_NewGame(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + NewGameInitData(); + player_avatar_init_params_reset(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = ExecuteTruckSequence; + gUnknown_03005DB0 = NULL; + do_load_map_stuff_loop(&gMain.state); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); +} + +void CB2_WhiteOut(void) +{ + u8 val; + + if (++gMain.state >= 120) + { + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + DoWhiteOut(); + player_avatar_init_params_reset(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = sub_80AF3C8; + val = 0; + do_load_map_stuff_loop(&val); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_LoadMap(void) +{ + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + SetMainCallback2(c2_change_map); + gMain.savedCallback = CB2_LoadMap2; +} + +static void CB2_LoadMap2(void) +{ + do_load_map_stuff_loop(&gMain.state); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); +} + +void sub_8086024(void) +{ + if (!gMain.state) + { + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + } + if (load_map_stuff(&gMain.state, 1)) + { + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); + } +} + +void sub_8086074(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF314; + SetMainCallback2(c2_80567AC); +} + +static void c2_80567AC(void) +{ + if (map_loading_iteration_3(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback1(c1_link_related); + sub_8086C2C(); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToField(void) +{ + if (is_c1_link_related_active() == TRUE) + { + SetMainCallback2(CB2_ReturnToFieldLink); + } + else + { + FieldClearVBlankHBlankCallbacks(); + SetMainCallback2(CB2_ReturnToFieldLocal); + } +} + +void CB2_ReturnToFieldLocal(void) +{ + if (sub_8086638(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToFieldLink(void) +{ + if (!sub_8087598() && map_loading_iteration_2_link(&gMain.state)) + SetMainCallback2(CB2_Overworld); +} + +void c2_8056854(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + SetMainCallback1(c1_link_related); + sub_8086C2C(); + + if (gWirelessCommType != 0) + gFieldCallback = sub_80AF314; + else + gFieldCallback = sub_80AF214; + + ScriptContext1_Init(); + ScriptContext2_Disable(); + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldWithOpenMenu(void) +{ + FieldClearVBlankHBlankCallbacks(); + gUnknown_03005DB0 = sub_80AF6A4; + CB2_ReturnToField(); +} + +void sub_80861B0(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF188; + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldContinueScript(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF168; + CB2_ReturnToField(); +} + +void sub_80861E8(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF3C8; + CB2_ReturnToField(); +} + +static void sub_8086204(void) +{ + if ((gMapHeader.flags & 0xF8) == 8 && sub_80E909C() == TRUE) + ShowMapNamePopup(); + sub_80AF3C8(); +} + +void CB2_ContinueSavedGame(void) +{ + u8 trainerHillMapId; + + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + if (gSaveFileStatus == 0xFF) + sub_81A3908(); + + LoadSaveblockMapHeader(); + set_warp2_warp3_to_neg_1(); + trainerHillMapId = GetCurrentTrainerHillMapId(); + if (gMapHeader.mapDataId == 0x169) + sub_81AA2F8(); + else if (trainerHillMapId != 0 && trainerHillMapId != 6) + sub_81D5F48(); + else + LoadSaveblockMapObjScripts(); + + UnfreezeMapObjects(); + DoTimeBasedEvents(); + sub_8084788(); + if (gMapHeader.mapDataId == 0x169) + battle_pyramid_map_load_related(1); + else if (trainerHillMapId != 0) + trainer_hill_map_load_related(); + else + sub_8087D74(); + + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + sub_8195E10(); + if (GetSecretBase2Field_9() == 1) + { + ClearSecretBase2Field_9(); + warp1_set_to_sav1w(); + warp_in(); + sub_80EDB44(); + SetMainCallback2(CB2_LoadMap); + } + else + { + sub_80EDB44(); + gFieldCallback = sub_8086204; + SetMainCallback1(CB1_Overworld); + CB2_ReturnToField(); + } +} + +static void FieldClearVBlankHBlankCallbacks(void) +{ + if (warp0_in_pokecenter() == TRUE) + CloseLink(); + + if (gWirelessCommType != 0) + { + EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + DisableInterrupts(INTR_FLAG_HBLANK); + } + else + { + u16 savedIme = REG_IME; + REG_IME = 0; + REG_IE &= ~INTR_FLAG_HBLANK; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = savedIme; + } + + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +static void SetFieldVBlankCallback(void) +{ + SetVBlankCallback(VBlankCB_Field); +} + +static void VBlankCB_Field(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + ScanlineEffect_InitHBlankDmaTransfer(); + FieldUpdateBgTilemapScroll(); + TransferPlttBuffer(); + TransferTilesetAnimsBuffer(); +} + +static void sub_80863B0(void) +{ + u8 val; + + if (sub_81A9E6C()) + { + door_upload_tiles(); + ScanlineEffect_SetParams(gUnknown_08339DBC); + } + else if ((val = Overworld_GetFlashLevel())) + { + sub_80B00E8(val); + ScanlineEffect_SetParams(gUnknown_08339DBC); + } +} + +static bool32 map_loading_iteration_3(u8 *state) +{ + switch (*state) + { + case 0: + overworld_bg_setup(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + sub_80867C8(); + sub_80867D8(); + (*state)++; + break; + case 1: + mli0_load_map(1); + (*state)++; + break; + case 2: + sub_8086988(TRUE); + (*state)++; + break; + case 3: + sub_8086AE4(); + sub_80869DC(); + sub_8086B14(); + sub_8086AAC(); + (*state)++; + break; + case 4: + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + (*state)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 6: + copy_map_tileset1_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 7: + copy_map_tileset2_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 8: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*state)++; + } + break; + case 9: + DrawWholeMapView(); + (*state)++; + break; + case 10: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*state)++; + break; + case 11: + if (gWirelessCommType != 0) + { + sub_800E0E8(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 13: + return TRUE; + } + + return FALSE; +} + +static bool32 load_map_stuff(u8 *state, u32 a2) +{ + switch (*state) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + mli0_load_map(a2); + (*state)++; + break; + case 1: + sub_80867C8(); + sub_80867D8(); + (*state)++; + break; + case 2: + sub_8086988(a2); + (*state)++; + break; + case 3: + mli4_mapscripts_and_other(); + sub_8086A80(); + (*state)++; + break; + case 4: + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + (*state)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 6: + copy_map_tileset1_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 7: + copy_map_tileset2_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 8: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*state)++; + } + break; + case 9: + DrawWholeMapView(); + (*state)++; + break; + case 10: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*state)++; + break; + case 11: + if ((gMapHeader.flags & 0xF8) == 8 && sub_80E909C() == 1) + ShowMapNamePopup(); + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 13: + return TRUE; + } + + return FALSE; +} + +static bool32 sub_8086638(u8 *state) +{ + switch (*state) + { + case 0: + sub_80867C8(); + sub_80867D8(); + sub_8086988(0); + sub_8086A68(); + sub_8086A80(); + (*state)++; + break; + case 1: + sub_8086860(); + sub_81D64C0(); + (*state)++; + break; + case 2: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 3: + return TRUE; + } + + return FALSE; +} + +static bool32 map_loading_iteration_2_link(u8 *state) +{ + switch (*state) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + sub_80867C8(); + sub_80867D8(); + (*state)++; + break; + case 1: + sub_8086988(1); + (*state)++; + break; + case 2: + sub_8086B9C(); + sub_8086A68(); + sub_8086AC8(); + (*state)++; + break; + case 3: + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + (*state)++; + break; + case 4: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 5: + copy_map_tileset1_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 6: + copy_map_tileset2_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 7: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*state)++; + } + break; + case 8: + DrawWholeMapView(); + (*state)++; + break; + case 9: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*state)++; + break; + case 11: + if (gWirelessCommType != 0) + { + sub_800E0E8(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 10: + (*state)++; + break; + case 13: + SetFieldVBlankCallback(); + (*state)++; + return TRUE; + } + + return FALSE; +} + +static void do_load_map_stuff_loop(u8 *state) +{ + while (!load_map_stuff(state, 0)); +} + +static void sub_80867C8(void) +{ + sub_81BE6AC(); + MoveSaveBlocks_ResetHeap(); +} + +static void sub_80867D8(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + ScanlineEffect_Stop(); + + DmaClear16(3, PLTT + 2, PLTT_SIZE - 2); + DmaFillLarge16(3, 0, (void *)(VRAM + 0x0), 0x18000, 0x1000); + ResetOamRange(0, 128); + LoadOam(); +} + +static void sub_8086860(void) +{ + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + mapdata_load_assets_to_gpu_and_full_redraw(); +} + +static void map_loading_lcd_reset(void) +{ + clear_scheduled_bg_copies_to_vram(); + reset_temp_tile_data_buffers(); + SetGpuReg(REG_OFFSET_MOSAIC, 0); + SetGpuReg(REG_OFFSET_WININ, 0x1F1F); + SetGpuReg(REG_OFFSET_WINOUT, 0x101); + SetGpuReg(REG_OFFSET_WIN0H, 0xFF); + 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] + | BLDCNT_TGT2_OBJ | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(13, 7)); + overworld_bg_setup(); + schedule_bg_copy_tilemap_to_vram(1); + schedule_bg_copy_tilemap_to_vram(2); + schedule_bg_copy_tilemap_to_vram(3); + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON + | DISPCNT_OBJ_1D_MAP | DISPCNT_HBLANK_INTERVAL); + ShowBg(0); + ShowBg(1); + ShowBg(2); + ShowBg(3); + sub_8098128(); +} + +static void sub_8086988(u32 a1) +{ + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + ScanlineEffect_Clear(); + dp13_810BB8C(); + ResetCameraUpdateInfo(); + InstallCameraPanAheadCallback(); + if (!a1) + npc_paltag_set_load(0); + else + npc_paltag_set_load(1); + + FieldEffectActiveListClear(); + sub_80AAFA4(); + sub_80AEE84(); + if (!a1) + SetUpFieldTasks(); + mapheader_run_script_with_tag_x5(); + sub_81BE6B8(); +} + +static void sub_80869DC(void) +{ + gUnknown_03005DEC = 0; + gUnknown_03005DE8 = 0; + sub_808D438(); + SpawnFieldObjectsInView(0, 0); + mapheader_run_first_tag4_script_list_match(); +} + +static void mli4_mapscripts_and_other(void) +{ + s16 x, y; + struct UnkPlayerStruct *player; + + gUnknown_03005DEC = 0; + gUnknown_03005DE8 = 0; + sub_808D438(); + sav1_camera_get_focus_coords(&x, &y); + player = sub_80852D4(); + InitPlayerAvatar(x, y, player->player_field_1, gSaveBlock2Ptr->playerGender); + SetPlayerAvatarTransitionFlags(player->player_field_0); + player_avatar_init_params_reset(); + SpawnFieldObjectsInView(0, 0); + mapheader_run_first_tag4_script_list_match(); +} + +static void sub_8086A68(void) +{ + sub_808E16C(0, 0); + RotatingGate_InitPuzzleAndGraphics(); + mapheader_run_script_with_tag_x7(); +} + +static void sub_8086A80(void) +{ + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_15 = 1; + InitCameraUpdateCallback(gPlayerAvatar.spriteId); +} + +static void sub_8086AAC(void) +{ + InitCameraUpdateCallback(sub_8087858(gUnknown_03005DB4)); +} + +static void sub_8086AC8(void) +{ + InitCameraUpdateCallback(sub_8087858(gUnknown_03005DB4)); +} + +static void sub_8086AE4(void) +{ + u16 x, y; + sav1_camera_get_focus_coords(&x, &y); + sub_8088B3C(x + gUnknown_03005DB4, y); +} + +static void sub_8086B14(void) +{ + u16 i; + u16 x, y; + + sav1_camera_get_focus_coords(&x, &y); + x -= gUnknown_03005DB4; + + for (i = 0; i < gFieldLinkPlayerCount; i++) + { + SpawnLinkPlayerMapObject(i, i + x, y, gLinkPlayers[i].gender); + CreateLinkPlayerSprite(i, gLinkPlayers[i].version); + } + + sub_8086C40(); +} + +static void sub_8086B9C(void) +{ + u16 i; + for (i = 0; i < gFieldLinkPlayerCount; i++) + CreateLinkPlayerSprite(i, gLinkPlayers[i].version); +} + +static void c1_link_related(void) +{ + if (gWirelessCommType == 0 || !sub_800F0B8() || !sub_8009F3C()) + { + u8 var = gUnknown_03005DB4; + sub_8086F38(gLinkPartnersHeldKeys, var); + sub_8086FA0(sUnknown_03000E14(var)); + sub_8086C40(); + } +} + +void sub_8086C2C(void) +{ + sub_8086C90(); + c1_link_related_func_set(sub_80870B0); +} + +static void sub_8086C40(void) +{ + sub_808709C(gLinkPartnersHeldKeys); +} + +static void c1_link_related_func_set(u16 (*func)(u32)) +{ + sUnknown_03000E19 = 0; + sUnknown_03000E14 = func; +} + +static void sub_8086C64(void) +{ + if (gWirelessCommType != 0 && ++sUnknown_03000E19 > 60) + sub_8010198(); +} + +static void sub_8086C90(void) +{ + s32 i; + for (i = 0; i < 4; i++) + sUnknown_03000E10[i] = 0x80; +} + +static bool32 sub_8086CA8(u16 a1) +{ + s32 i; + s32 count = gFieldLinkPlayerCount; + + for (i = 0; i < count; i++) + if (sUnknown_03000E10[i] != a1) + return FALSE; + return TRUE; +} + +static bool32 sub_8086CE0(u16 a1) +{ + s32 i; + s32 count = gFieldLinkPlayerCount; + + for (i = 0; i < count; i++) + if (sUnknown_03000E10[i] == a1) + return TRUE; + return FALSE; +} + +static void sub_8086D18(u32 a1, u16 a2, struct UnkStruct_8054FF8 *a3, u16 *a4) +{ + const u8 *script; + + if (sUnknown_03000E10[a1] == 0x80) + { + script = sub_8087370(a3); + if (script) + { + *a4 = sub_8087480(script); + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_8087530(script); + } + return; + } + if (sub_8086CE0(0x83) == 1) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_8087584(); + } + return; + } + switch (a2) + { + case 24: + if (sub_8087358(a3)) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_808751C(); + } + } + break; + case 18: + if (sub_8087388(a3) == TRUE) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_808754C(); + } + } + break; + case 25: + script = sub_80873B4(a3); + if (script) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_8087568(script); + } + } + break; + case 27: + if (sub_8087340(a3)) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_808711C); + sub_8087510(); + } + } + break; + case 28: + if (sub_8087340(a3)) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_8087140); + sub_8087510(); + } + } + break; + } + } + + switch (a2) + { + case 23: + sUnknown_03000E10[a1] = 0x83; + break; + case 22: + sUnknown_03000E10[a1] = 0x82; + break; + case 26: + sUnknown_03000E10[a1] = 0x80; + if (a3->b) + c1_link_related_func_set(sub_80870B0); + break; + case 29: + if (sUnknown_03000E10[a1] == 0x82) + sUnknown_03000E10[a1] = 0x81; + break; + } +} + +static void sub_8086F38(u16 *a1, s32 a2) +{ + struct UnkStruct_8054FF8 st; + 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); + } +} + +static void sub_8086FA0(u16 a1) +{ + if (a1 >= 17 && a1 < 30) + gUnknown_03005DA8 = a1; + else + gUnknown_03005DA8 = 17; + + if (gWirelessCommType != 0 + && sub_8087690() > 1 + && is_c1_link_related_active() == TRUE + && sub_8009F3C() == TRUE) + { + switch (a1) + { + case 17: + case 18: + case 19: + case 20: + case 21: + case 24: + case 25: + gUnknown_03005DA8 = 0; + break; + } + } +} + +static u16 sub_808700C(u32 a1) +{ + if (gMain.heldKeys & DPAD_UP) + return 19; + else if (gMain.heldKeys & DPAD_DOWN) + return 18; + else if (gMain.heldKeys & DPAD_LEFT) + return 20; + else if (gMain.heldKeys & DPAD_RIGHT) + return 21; + else if (gMain.newKeys & START_BUTTON) + return 24; + else if (gMain.newKeys & A_BUTTON) + return 25; + else + return 17; +} + +static u16 sub_8087068(u16 a1) +{ + switch (a1) + { + case 21: + return 4; + case 20: + return 3; + case 19: + return 1; + case 18: + return 2; + default: + return 0; + } +} + +static void sub_808709C(u16 *a1) +{ + s32 i; + for (i = 0; i < 4; i++) + a1[i] = 17; +} + +static u16 sub_80870B0(u32 a1) +{ + if (ScriptContext2_IsEnabled() == 1) + return 17; + if (sub_800B4DC() > 4) + return 27; + if (sub_8087690() <= 4) + return sub_808700C(a1); + return 28; +} + +static u16 sub_80870EC(u32 a1) +{ + sub_8086C64(); + return 17; +} + +static u16 sub_80870F8(u32 a1) +{ + u16 retVal; + if (ScriptContext2_IsEnabled() == TRUE) + { + retVal = 17; + } + else + { + retVal = 26; + c1_link_related_func_set(sub_80870EC); + } + return retVal; +} + +static u16 sub_808711C(u32 a1) +{ + u16 retVal; + if (sub_800B4DC() > 2) + { + retVal = 17; + } + else + { + retVal = 26; + ScriptContext2_Disable(); + c1_link_related_func_set(sub_80870EC); + } + return retVal; +} + +static u16 sub_8087140(u32 a1) +{ + u16 retVal; + if (sub_8087690() > 2) + { + retVal = 17; + } + else + { + retVal = 26; + ScriptContext2_Disable(); + c1_link_related_func_set(sub_80870EC); + } + return retVal; +} + +static u16 sub_8087164(u32 a1) +{ + sub_8086C64(); + return 17; +} + +static u16 sub_8087170(u32 linkPlayerId) +{ + if (sUnknown_03000E10[linkPlayerId] == 0x82) + { + if (gMain.newKeys & B_BUTTON) + { + c1_link_related_func_set(sub_8087164); + return 29; + } + else + { + return 17; + } + } + else + { + sub_8086C64(); + return 17; + } +} + +static u16 sub_80871AC(u32 a1) +{ + c1_link_related_func_set(sub_8087170); + return 22; +} + +static u16 sub_80871C0(u32 a1) +{ + return 17; +} + +static u16 sub_80871C4(u32 a1) +{ + if (sUnknown_03000E10[a1] != 0x83) + sub_8086C64(); + if (sub_8086CA8(0x83) == TRUE) + { + ScriptContext1_SetupScript(EventScript_277513); + c1_link_related_func_set(sub_80871C0); + } + return 17; +} + +static u16 sub_80871FC(u32 a1) +{ + c1_link_related_func_set(sub_80871C4); + return 23; +} + +static u16 sub_8087210(u32 a1) +{ + return 17; +} + +u32 sub_8087214(void) +{ + if (sub_8086CE0(0x83) == TRUE) + return 2; + if (sUnknown_03000E14 == sub_8087170 && sUnknown_03000E10[gUnknown_03005DB4] != 0x82) + return 0; + if (sUnknown_03000E14 == sub_8087164 && sUnknown_03000E10[gUnknown_03005DB4] == 0x81) + return 2; + if (sub_8086CA8(0x82) != 0) + return 1; + return 0; +} + +bool32 sub_808727C(void) +{ + return sub_8086CE0(0x83); +} + +u16 sub_8087288(void) +{ + c1_link_related_func_set(sub_80871AC); + return 0; +} + +u16 sub_808729C(void) +{ + c1_link_related_func_set(sub_80870F8); + return 0; +} + +u16 sub_80872B0(void) +{ + c1_link_related_func_set(sub_80871FC); + return 0; +} + +u16 sub_80872C4(void) +{ + c1_link_related_func_set(sub_8087210); + return 0; +} + +static void sub_80872D8(s32 linkPlayerId, s32 a2, struct UnkStruct_8054FF8 *a3) +{ + s16 x, y; + + a3->a = linkPlayerId; + a3->b = (linkPlayerId == a2) ? 1 : 0; + a3->c = gLinkPlayerMapObjects[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); +} + +static bool32 sub_8087340(struct UnkStruct_8054FF8 *a1) +{ + u8 v1 = a1->c; + if (v1 == 2 || v1 == 0) + return TRUE; + else + return FALSE; +} + +static bool32 sub_8087358(struct UnkStruct_8054FF8 *a1) +{ + u8 v1 = a1->c; + if (v1 == 2 || v1 == 0) + return TRUE; + else + return FALSE; +} + +static u8 *sub_8087370(struct UnkStruct_8054FF8 *a1) +{ + if (a1->c != 2) + return 0; + return sub_809D0F4(&a1->sub); +} + +static bool32 sub_8087388(struct UnkStruct_8054FF8 *a1) +{ + if (a1->c != 2 && a1->c != 0) + return FALSE; + else if (!MetatileBehavior_IsSouthArrowWarp(a1->field_C)) + return FALSE; + else if (a1->d != 1) + return FALSE; + else + return TRUE; +} + +static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1) +{ + struct MapPosition unkStruct; + u8 linkPlayerId; + + if (a1->c && a1->c != 2) + return 0; + + unkStruct = a1->sub; + unkStruct.x += gUnknown_08339D64[a1->d].x; + unkStruct.y += gUnknown_08339D64[a1->d].y; + unkStruct.height = 0; + linkPlayerId = GetLinkPlayerIdAt(unkStruct.x, unkStruct.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; + else + return EventScript_TradeRoom_ReadTrainerCard2; + } + + return sub_809C2C8(&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; + else + return 0; +} + +static void sub_8087510(void) +{ + ScriptContext2_Enable(); +} + +static void sub_808751C(void) +{ + PlaySE(SE_WIN_OPEN); + sub_809FA9C(); + ScriptContext2_Enable(); +} + +static void sub_8087530(const u8 *script) +{ + PlaySE(SE_SELECT); + ScriptContext1_SetupScript(script); + ScriptContext2_Enable(); +} + +static void sub_808754C(void) +{ + PlaySE(SE_WIN_OPEN); + ScriptContext1_SetupScript(gUnknown_082774EF); + ScriptContext2_Enable(); +} + +static void sub_8087568(const u8 *script) +{ + PlaySE(SE_SELECT); + ScriptContext1_SetupScript(script); + ScriptContext2_Enable(); +} + +static void sub_8087584(void) +{ + ScriptContext1_SetupScript(gUnknown_08277509); + ScriptContext2_Enable(); +} + +bool32 sub_8087598(void) +{ + if (!is_c1_link_related_active()) + return 0; + if (sub_800B4DC() >= 3) + sUnknown_03000E18 = 1; + else + sUnknown_03000E18 = 0; + return sUnknown_03000E18; +} + +bool32 sub_80875C8(void) +{ + u8 temp; + + if (sub_800B4DC() < 2) + return FALSE; + else if (is_c1_link_related_active() != TRUE) + return FALSE; + else if (sub_8009F3C() != TRUE) + return FALSE; + else if (sUnknown_03000E14 == sub_808711C) + return TRUE; + else if (sUnknown_03000E14 != sub_80870F8) + return FALSE; + + temp = sUnknown_03000E18; + sUnknown_03000E18 = 0; + + if (temp == TRUE) + return TRUE; + else if (gPaletteFade.active && gPaletteFade.softwareFadeFinishing) + return TRUE; + else + return FALSE; +} + +bool32 sub_8087634(void) +{ + if (sub_8087690() < 2) + return FALSE; + else if (is_c1_link_related_active() != TRUE) + return FALSE; + else if (sub_8009F3C() != TRUE) + return FALSE; + else if (sUnknown_03000E14 == sub_8087140) + return TRUE; + else + return FALSE; +} + +bool32 sub_808766C(void) +{ + if (gWirelessCommType != 0) + return FALSE; + else if (!sub_8009F3C()) + return FALSE; + else + return TRUE; +} + +static u32 sub_8087690(void) +{ + if (gWirelessCommType != 0) + return gUnknown_03005000.unk_9e8.unk_232; + else + return gLink.sendQueue.count; +} + +static void ZeroLinkPlayerMapObject(struct LinkPlayerMapObject *linkPlayerMapObj) +{ + memset(linkPlayerMapObj, 0, sizeof(struct LinkPlayerMapObject)); +} + +void ZeroAllLinkPlayerMapObjects(void) +{ + memset(gLinkPlayerMapObjects, 0, sizeof(gLinkPlayerMapObjects)); +} + +static void ZeroMapObject(struct MapObject *mapObj) +{ + memset(mapObj, 0, sizeof(struct MapObject)); +} + +static void SpawnLinkPlayerMapObject(u8 linkPlayerId, s16 x, s16 y, u8 a4) +{ + u8 mapObjId = sub_808D4F4(); + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + + ZeroLinkPlayerMapObject(linkPlayerMapObj); + ZeroMapObject(mapObj); + + linkPlayerMapObj->active = 1; + linkPlayerMapObj->linkPlayerId = linkPlayerId; + linkPlayerMapObj->mapObjId = mapObjId; + linkPlayerMapObj->mode = 0; + + mapObj->active = 1; + mapObj->mapobj_bit_1 = a4; + mapObj->range.as_byte = 2; + mapObj->spriteId = 64; + + InitLinkPlayerMapObjectPos(mapObj, x, y); +} + +static void InitLinkPlayerMapObjectPos(struct MapObject *mapObj, s16 x, s16 y) +{ + mapObj->coords2.x = x; + mapObj->coords2.y = y; + mapObj->coords3.x = x; + mapObj->coords3.y = y; + sub_8093038(x, y, &mapObj->coords1.x, &mapObj->coords1.y); + mapObj->coords1.x += 8; + FieldObjectUpdateZCoord(mapObj); +} + +static void sub_80877DC(u8 linkPlayerId, u8 a2) +{ + if (gLinkPlayerMapObjects[linkPlayerId].active) + { + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + mapObj->range.as_byte = a2; + } +} + +static void sub_808780C(u8 linkPlayerId) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + if (mapObj->spriteId != 64 ) + DestroySprite(&gSprites[mapObj->spriteId]); + linkPlayerMapObj->active = 0; + mapObj->active = 0; +} + +static u8 sub_8087858(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->spriteId; +} + +static void sub_8087878(u8 linkPlayerId, u16 *x, u16 *y) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + *x = mapObj->coords2.x; + *y = mapObj->coords2.y; +} + +static u8 sub_80878A0(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->range.as_byte; +} + +static u8 sub_80878C0(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->mapobj_unk_0B_0; +} + +static s32 sub_80878E4(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return 16 - (s8)mapObj->mapobj_unk_21; +} + +static u8 GetLinkPlayerIdAt(s16 x, s16 y) +{ + u8 i; + for (i = 0; i < 4; i++) + { + if (gLinkPlayerMapObjects[i].active + && (gLinkPlayerMapObjects[i].mode == 0 || gLinkPlayerMapObjects[i].mode == 2)) + { + struct MapObject *mapObj = &gMapObjects[gLinkPlayerMapObjects[i].mapObjId]; + if (mapObj->coords2.x == x && mapObj->coords2.y == y) + return i; + } + } + return 4; +} + +static void sub_808796C(u8 linkPlayerId, u8 a2) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + + if (linkPlayerMapObj->active) + { + if (a2 > 10) + mapObj->mapobj_bit_2 = 1; + else + gUnknown_08339E00[gUnknown_08339DC8[linkPlayerMapObj->mode](linkPlayerMapObj, mapObj, a2)](linkPlayerMapObj, mapObj); + } +} + +static u8 sub_80879D8(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return gUnknown_08339DD4[a3](linkPlayerMapObj, mapObj, a3); +} + +static u8 sub_80879F8(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return 1; +} + +static u8 sub_80879FC(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return gUnknown_08339DD4[a3](linkPlayerMapObj, mapObj, a3); +} + +static u8 sub_8087A1C(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return 0; +} + +static u8 sub_8087A20(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + s16 x, y; + + mapObj->range.as_byte = npc_something3(a3, mapObj->range.as_byte); + FieldObjectMoveDestCoords(mapObj, mapObj->range.as_byte, &x, &y); + + if (LinkPlayerDetectCollision(linkPlayerMapObj->mapObjId, mapObj->range.as_byte, x, y)) + { + return 0; + } + else + { + mapObj->mapobj_unk_21 = 16; + npc_coords_shift(mapObj, x, y); + FieldObjectUpdateZCoord(mapObj); + return 1; + } +} + +static u8 sub_8087A88(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + mapObj->range.as_byte = npc_something3(a3, mapObj->range.as_byte); + return 0; +} + +static void sub_8087AA0(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj) +{ + linkPlayerMapObj->mode = 0; +} + +static void sub_8087AA8(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj) +{ + mapObj->mapobj_unk_21--; + linkPlayerMapObj->mode = 1; + MoveCoords(mapObj->range.as_byte, &mapObj->coords1.x, &mapObj->coords1.y); + if (!mapObj->mapobj_unk_21) + { + npc_coords_shift_still(mapObj); + linkPlayerMapObj->mode = 2; + } +} + +static u8 npc_something3(u8 a1, u8 a2) +{ + switch (a1 - 1) + { + case 0: + case 6: + return 2; + case 1: + case 7: + return 1; + case 2: + case 8: + return 3; + case 3: + case 9: + return 4; + } + return a2; +} + +static u8 LinkPlayerDetectCollision(u8 selfMapObjId, u8 a2, s16 x, s16 y) +{ + u8 i; + for (i = 0; i < 16; i++) + { + if (i != selfMapObjId) + { + if ((gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y) + || (gMapObjects[i].coords3.x == x && gMapObjects[i].coords3.y == y)) + { + return 1; + } + } + } + return MapGridIsImpassableAt(x, y); +} + +static void CreateLinkPlayerSprite(u8 linkPlayerId, u8 gameVersion) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + struct Sprite *sprite; -// Static type declarations + if (linkPlayerMapObj->active) + { + switch (gameVersion) + { + case VERSION_FIRE_RED: + case VERSION_LEAF_GREEN: + mapObj->spriteId = AddPseudoFieldObject(sub_808BD6C(mapObj->mapobj_bit_1), SpriteCB_LinkPlayer, 0, 0, 0); + break; + case VERSION_RUBY: + case VERSION_SAPPHIRE: + mapObj->spriteId = AddPseudoFieldObject(sub_808BD7C(mapObj->mapobj_bit_1), SpriteCB_LinkPlayer, 0, 0, 0); + break; + case VERSION_EMERALD: + mapObj->spriteId = AddPseudoFieldObject(GetRivalAvatarGraphicsIdByStateIdAndGender(0, mapObj->mapobj_bit_1), SpriteCB_LinkPlayer, 0, 0, 0); + break; + } -// Static RAM declarations -IWRAM_DATA void *gUnknown_03000E0C; -IWRAM_DATA u8 gUnknown_03000E10[4]; -IWRAM_DATA u8 (*gUnknown_03000E14)(u32); -IWRAM_DATA u8 gUnknown_03000E18; -IWRAM_DATA u8 gUnknown_03000E19; -IWRAM_DATA void *rom4_c_unused_03000e1c; + sprite = &gSprites[mapObj->spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->data[0] = linkPlayerId; + mapObj->mapobj_bit_2 = 0; + } +} -// Static ROM declarations +static void SpriteCB_LinkPlayer(struct Sprite *sprite) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[sprite->data[0]]; + struct MapObject *mapObj = &gMapObjects[linkPlayerMapObj->mapObjId]; + sprite->pos1.x = mapObj->coords1.x; + sprite->pos1.y = mapObj->coords1.y; + SetObjectSubpriorityByZCoord(mapObj->elevation, sprite, 1); + sprite->oam.priority = ZCoordToPriority(mapObj->elevation); -// .rodata + if (!linkPlayerMapObj->mode) + StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObj->range.as_byte)); + else + StartSpriteAnimIfDifferent(sprite, get_go_image_anim_num(mapObj->range.as_byte)); -// .text + sub_80979D4(sprite, 0); + if (mapObj->mapobj_bit_2) + { + sprite->invisible = ((sprite->data[7] & 4) >> 2); + sprite->data[7]++; + } +} |