diff options
Diffstat (limited to 'src/overworld.c')
-rw-r--r-- | src/overworld.c | 2465 |
1 files changed, 2465 insertions, 0 deletions
diff --git a/src/overworld.c b/src/overworld.c new file mode 100644 index 000000000..4fb6be314 --- /dev/null +++ b/src/overworld.c @@ -0,0 +1,2465 @@ +#include "global.h" +#include "gflib.h" +#include "bg_regs.h" +#include "event_data.h" +#include "event_object_movement.h" +#include "event_scripts.h" +#include "field_camera.h" +#include "field_control_avatar.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_message_box.h" +#include "field_player_avatar.h" +#include "field_screen_effect.h" +#include "field_specials.h" +#include "field_tasks.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "heal_location.h" +#include "help_system.h" +#include "link.h" +#include "load_save.h" +#include "m4a.h" +#include "map_name_popup.h" +#include "map_preview_screen.h" +#include "metatile_behavior.h" +#include "money.h" +#include "new_game.h" +#include "new_menu_helpers.h" +#include "overworld.h" +#include "play_time.h" +#include "quest_log.h" +#include "quest_log_objects.h" +#include "random.h" +#include "renewable_hidden_items.h" +#include "roamer.h" +#include "safari_zone.h" +#include "save_location.h" +#include "scanline_effect.h" +#include "script.h" +#include "script_pokemon_util.h" +#include "tileset_anims.h" +#include "trainer_pokemon_sprites.h" +#include "vs_seeker.h" +#include "wild_encounter.h" +#include "constants/maps.h" +#include "constants/flags.h" +#include "constants/species.h" +#include "constants/region_map_sections.h" +#include "constants/songs.h" + +struct InitialPlayerAvatarState +{ + u8 transitionFlags; + u8 direction; + bool8 unk2; +}; + +EWRAM_DATA struct WarpData gLastUsedWarp = {}; +EWRAM_DATA struct WarpData sWarpDestination = {}; +EWRAM_DATA struct WarpData gFixedDiveWarp = {}; +EWRAM_DATA struct WarpData gFixedHoleWarp = {}; + +// File boundary perhaps? +EWRAM_DATA struct InitialPlayerAvatarState gInitialPlayerAvatarState = {}; + +// File boundary perhaps? +EWRAM_DATA bool8 gDisableMapMusicChangeOnMapLoad = FALSE; +EWRAM_DATA u16 sAmbientCrySpecies = SPECIES_NONE; +EWRAM_DATA bool8 sIsAmbientCryWaterMon = FALSE; + +// File boundary perhaps? +ALIGNED(4) EWRAM_DATA bool8 gUnknown_2031DE0 = FALSE; +EWRAM_DATA const struct CreditsOverworldCmd *gUnknown_2031DE4 = NULL; +EWRAM_DATA s16 gUnknown_2031DE8 = 0; +EWRAM_DATA s16 gUnknown_2031DEA = 0; + +// File boundary perhaps? +EWRAM_DATA struct LinkPlayerObjectEvent gLinkPlayerObjectEvents[4] = {}; + +u16 *gBGTilemapBuffers1; +u16 *gBGTilemapBuffers2; +u16 *gBGTilemapBuffers3; +void (*gFieldCallback)(void); +bool8 (*gFieldCallback2)(void); +u16 gHeldKeyCodeToSend; +u8 gLocalLinkPlayerId; +u8 gFieldLinkPlayerCount; + +u8 CountBadgesForOverworldWhiteOutLossCalculation(void); +void Overworld_ResetStateAfterWhitingOut(void); +void Overworld_SetWhiteoutRespawnPoint(void); +u8 GetAdjustedInitialTransitionFlags(struct InitialPlayerAvatarState *playerStruct, u16 metatileBehavior, u8 mapType); +u8 GetAdjustedInitialDirection(struct InitialPlayerAvatarState *playerStruct, u8 transitionFlags, u16 metatileBehavior, u8 mapType); +u16 GetCenterScreenMetatileBehavior(void); +bool8 sub_8055B38(u16 metatileBehavior); +void SetDefaultFlashLevel(void); +void Overworld_TryMapConnectionMusicTransition(void); +void ChooseAmbientCrySpecies(void); + +void CB2_Overworld(void); +void CB2_DoChangeMap(void); +void CB2_LoadMap2(void); +void c2_80567AC(void); +void CB2_ReturnToFieldLocal(void); +void CB2_ReturnToFieldLink(void); +void FieldClearVBlankHBlankCallbacks(void); +void SetFieldVBlankCallback(void); +void VBlankCB_Field(void); + +bool32 map_loading_iteration_3(u8 *state); +bool32 sub_8056CD8(u8 *state); +bool32 map_loading_iteration_2_link(u8 *state); +void do_load_map_stuff_loop(u8 *state); +void MoveSaveBlocks_ResetHeap_(void); +void sub_8056E80(void); +void sub_8056F08(void); +void InitOverworldGraphicsRegisters(void); +void sub_8057024(bool32 a0); +void sub_8057074(void); +void mli4_mapscripts_and_other(void); +void sub_8057100(void); +void sub_8057114(void); +void SetCameraToTrackGuestPlayer(void); +void SetCameraToTrackGuestPlayer_2(void); +void sub_8057178(void); +void sub_80571A8(void); +void CreateLinkPlayerSprites(void); +void sub_80572D8(void); +void sub_8057300(u8 *state); +bool32 sub_8057314(u8 *state); +bool32 sub_8057528(u8 *state, u8 unused); +bool8 sub_8057650(void); +void sub_8057748(struct CameraObject * camera); +void sub_805781C(u8 taskId); +void sub_8057854(u8 taskId); +void SpawnLinkPlayerObjectEvent(u8 i, s16 x, s16 y, u8 gender); +void CreateLinkPlayerSprite(u8 i, u8 version); +void ClearAllPlayerKeys(void); +u8 GetSpriteForLinkedPlayer(u8 linkPlayerId); +void CB1_UpdateLinkState(void); +void ResetAllMultiplayerState(void); + +extern const struct MapLayout * gMapLayouts[]; +extern const struct MapHeader *const *gMapGroups[]; + +// Routines related to game state on warping in + +static const u8 sWhiteOutMoneyLossMultipliers[] = { + 2, + 4, + 6, + 9, + 12, + 16, + 20, + 25, + 30 +}; + +const u16 sWhiteOutMoneyLossBadgeFlagIDs[] = { + FLAG_BADGE01_GET, + FLAG_BADGE02_GET, + FLAG_BADGE03_GET, + FLAG_BADGE04_GET, + FLAG_BADGE05_GET, + FLAG_BADGE06_GET, + FLAG_BADGE07_GET, + FLAG_BADGE08_GET +}; + +void DoWhiteOut(void) +{ + ScriptContext2_RunNewScript(EventScript_ResetEliteFourEnd); + RemoveMoney(&gSaveBlock1Ptr->money, ComputeWhiteOutMoneyLoss()); + HealPlayerParty(); + Overworld_ResetStateAfterWhitingOut(); + Overworld_SetWhiteoutRespawnPoint(); + WarpIntoMap(); +} + +u32 ComputeWhiteOutMoneyLoss(void) +{ + u8 nbadges = CountBadgesForOverworldWhiteOutLossCalculation(); + u8 toplevel = GetPlayerPartyHighestLevel(); + u32 losings = toplevel * 4 * sWhiteOutMoneyLossMultipliers[nbadges]; + u32 money = GetMoney(&gSaveBlock1Ptr->money); + if (losings > money) + losings = money; + return losings; +} + +void OverworldWhiteOutGetMoneyLoss(void) +{ + u32 losings = ComputeWhiteOutMoneyLoss(); + ConvertIntToDecimalStringN(gStringVar1, losings, STR_CONV_MODE_LEFT_ALIGN, CountDigits(losings)); +} + +u8 CountBadgesForOverworldWhiteOutLossCalculation(void) +{ + int i; + u8 nbadges = 0; + for (i = 0; i < NELEMS(sWhiteOutMoneyLossBadgeFlagIDs); i++) + { + if (FlagGet(sWhiteOutMoneyLossBadgeFlagIDs[i])) + nbadges++; + } + return nbadges; +} + +void Overworld_ResetStateAfterFly(void) +{ + ResetInitialPlayerAvatarState(); + FlagClear(FLAG_SYS_ON_CYCLING_ROAD); + VarSet(VAR_MAP_SCENE_ROUTE16, 0); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + VarSet(VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE, 0); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_FLASH_ACTIVE); + FlagClear(FLAG_0x808); + VarSet(VAR_0x404D, 0); +} + +void Overworld_ResetStateAfterTeleport(void) +{ + ResetInitialPlayerAvatarState(); + FlagClear(FLAG_SYS_ON_CYCLING_ROAD); + VarSet(VAR_MAP_SCENE_ROUTE16, 0); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + VarSet(VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE, 0); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_FLASH_ACTIVE); + FlagClear(FLAG_0x808); + VarSet(VAR_0x404D, 0); +} + +void Overworld_ResetStateAfterDigEscRope(void) +{ + ResetInitialPlayerAvatarState(); + FlagClear(FLAG_SYS_ON_CYCLING_ROAD); + VarSet(VAR_MAP_SCENE_ROUTE16, 0); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + VarSet(VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE, 0); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_FLASH_ACTIVE); + FlagClear(FLAG_0x808); + VarSet(VAR_0x404D, 0); +} + +void Overworld_ResetStateAfterWhitingOut(void) +{ + ResetInitialPlayerAvatarState(); + FlagClear(FLAG_SYS_ON_CYCLING_ROAD); + VarSet(VAR_MAP_SCENE_ROUTE16, 0); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + VarSet(VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE, 0); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_FLASH_ACTIVE); + FlagClear(FLAG_0x808); + VarSet(VAR_0x404D, 0); +} + +void sub_8054E40(void) +{ + FlagClear(FLAG_SYS_SAFARI_MODE); + VarSet(VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE, 0); + ChooseAmbientCrySpecies(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); +} + +// Routines related to game stats + +void ResetGameStats(void) +{ + int i; + + for (i = 0; i < NUM_GAME_STATS; i++) + { + gSaveBlock1Ptr->gameStats[i] = 0; + } +} + +void IncrementGameStat(u8 statId) +{ + u32 statVal; + if (statId >= NUM_USED_GAME_STATS) + return; + statVal = GetGameStat(statId); + if (statVal < 0xFFFFFF) + statVal++; + else + statVal = 0xFFFFFF; + SetGameStat(statId, statVal); +} + +u32 GetGameStat(u8 statId) +{ + if (statId >= NUM_USED_GAME_STATS) + return 0; + else + return gSaveBlock1Ptr->gameStats[statId] ^ gSaveBlock2Ptr->encryptionKey; +} + +void SetGameStat(u8 statId, u32 statVal) +{ + if (statId >= NUM_USED_GAME_STATS) + return; + gSaveBlock1Ptr->gameStats[statId] = statVal ^ gSaveBlock2Ptr->encryptionKey; +} + +void ApplyNewEncryptionKeyToGameStats(u32 newKey) +{ + u8 i; + for (i = 0; i < NUM_GAME_STATS; i++) + { + ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->gameStats[i], newKey); + } +} + +// Routines related to object events + +void sub_8054F68(void) +{ + u8 i, j; + u8 mapGroup; + u8 mapNum; + u8 localId; + const struct MapHeader * linkedMap; + + for (i = 0, j = 0; i < gMapHeader.events->objectEventCount; i++) + { + if (gMapHeader.events->objectEvents[i].unk2 == 0xFF) + { + localId = gMapHeader.events->objectEvents[i].elevation; + mapNum = gMapHeader.events->objectEvents[i].trainerType; + mapGroup = gMapHeader.events->objectEvents[i].trainerRange_berryTreeId; + linkedMap = Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum); + gSaveBlock1Ptr->objectEventTemplates[j] = linkedMap->events->objectEvents[localId - 1]; + gSaveBlock1Ptr->objectEventTemplates[j].localId = gMapHeader.events->objectEvents[i].localId; + gSaveBlock1Ptr->objectEventTemplates[j].x = gMapHeader.events->objectEvents[i].x; + gSaveBlock1Ptr->objectEventTemplates[j].y = gMapHeader.events->objectEvents[i].y; + gSaveBlock1Ptr->objectEventTemplates[j].elevation = localId; + gSaveBlock1Ptr->objectEventTemplates[j].trainerType = mapNum; + gSaveBlock1Ptr->objectEventTemplates[j].trainerRange_berryTreeId = mapGroup; + gSaveBlock1Ptr->objectEventTemplates[j].unk2 = 0xFF; + j++; + } + else + { + gSaveBlock1Ptr->objectEventTemplates[j] = gMapHeader.events->objectEvents[i]; + j++; + } + } +} + +void LoadSaveblockObjEventScripts(void) +{ + int i; + const struct ObjectEventTemplate * src = gMapHeader.events->objectEvents; + struct ObjectEventTemplate * savObjTemplates = gSaveBlock1Ptr->objectEventTemplates; + + for (i = 0; i < OBJECT_EVENT_TEMPLATES_COUNT; i++) + { + savObjTemplates[i].script = src[i].script; + } +} + +void Overworld_SetMapObjTemplateCoords(u8 localId, s16 x, s16 y) +{ + int i; + struct ObjectEventTemplate * savObjTemplates = gSaveBlock1Ptr->objectEventTemplates; + for (i = 0; i < OBJECT_EVENT_TEMPLATES_COUNT; i++) + { + if (savObjTemplates[i].localId == localId) + { + savObjTemplates[i].x = x; + savObjTemplates[i].y = y; + break; + } + } +} + +void Overworld_SetObjEventTemplateMovementType(u8 localId, u8 movementType) +{ + s32 i; + + struct ObjectEventTemplate *savObjTemplates = gSaveBlock1Ptr->objectEventTemplates; + for (i = 0; i < OBJECT_EVENT_TEMPLATES_COUNT; i++) + { + struct ObjectEventTemplate *objectEventTemplate = &savObjTemplates[i]; + if (objectEventTemplate->localId == localId) + { + objectEventTemplate->movementType = movementType; + return; + } + } +} + +// Routines related to the map layout + +void mapdata_load_assets_to_gpu_and_full_redraw(void) +{ + move_tilemap_camera_to_upper_left_corner(); + copy_map_tileset1_tileset2_to_vram(gMapHeader.mapLayout); + apply_map_tileset1_tileset2_palette(gMapHeader.mapLayout); + DrawWholeMapView(); + InitTilesetAnimations(); +} + +const struct MapLayout *GetMapLayout(void) +{ + u16 mapLayoutId = gSaveBlock1Ptr->mapLayoutId; + if (mapLayoutId) + return gMapLayouts[mapLayoutId - 1]; + return NULL; +} + +// Routines related to warps + +const struct WarpData sDummyWarpData = { + .mapGroup = MAP_GROUP(UNDEFINED), + .mapNum = MAP_NUM(UNDEFINED), + .warpId = 0xFF, + .x = -1, + .y = -1 +}; + +void ApplyCurrentWarp(void) +{ + gLastUsedWarp = gSaveBlock1Ptr->location; + gSaveBlock1Ptr->location = sWarpDestination; + gFixedDiveWarp = sDummyWarpData; + gFixedHoleWarp = 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 IsDummyWarp(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; +} + +struct MapHeader const *const Overworld_GetMapHeaderByGroupAndId(u16 mapGroup, u16 mapNum) +{ + return gMapGroups[mapGroup][mapNum]; +} + +struct MapHeader const *const GetDestinationWarpMapHeader(void) +{ + return Overworld_GetMapHeaderByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); +} + +void LoadCurrentMapData(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gSaveBlock1Ptr->mapLayoutId = gMapHeader.mapLayoutId; + gMapHeader.mapLayout = GetMapLayout(); +} + +void LoadSaveblockMapHeader(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gMapHeader.mapLayout = GetMapLayout(); +} + +void SetPlayerCoordsFromWarp(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.mapLayout->width / 2; + gSaveBlock1Ptr->pos.y = gMapHeader.mapLayout->height / 2; + } +} + +void WarpIntoMap(void) +{ + ApplyCurrentWarp(); + LoadCurrentMapData(); + SetPlayerCoordsFromWarp(); +} + +void SetWarpDestination(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sWarpDestination, mapGroup, mapNum, warpId, x, y); +} + +void SetWarpDestinationToMapWarp(s8 mapGroup, s8 mapNum, s8 warpId) +{ + SetWarpDestination(mapGroup, mapNum, warpId, -1, -1); +} + +void SetDynamicWarp(s32 unused, s8 mapGroup, s8 mapNum, s8 warpId) +{ + SetWarpData(&gSaveBlock1Ptr->dynamicWarp, mapGroup, mapNum, warpId, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y); +} + +void SetDynamicWarpWithCoords(s32 unused, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->dynamicWarp, mapGroup, mapNum, warpId, x, y); +} + +void SetWarpDestinationToDynamicWarp(u8 unusedWarpId) +{ + sWarpDestination = gSaveBlock1Ptr->dynamicWarp; +} + +void SetWarpDestinationToHealLocation(u8 healLocationId) +{ + const struct HealLocation *warp = GetHealLocation(healLocationId); + if (warp) + SetWarpDestination(warp->group, warp->map, -1, warp->x, warp->y); +} + +void SetWarpDestinationToLastHealLocation(void) +{ + sWarpDestination = gSaveBlock1Ptr->lastHealLocation; +} + +void Overworld_SetWhiteoutRespawnPoint(void) +{ + SetWhiteoutRespawnWarpAndHealerNpc(&sWarpDestination); +} + +void SetLastHealLocationWarp(u8 healLocationId) +{ + const struct HealLocation *healLocation = GetHealLocation(healLocationId); + if (healLocation) + SetWarpData(&gSaveBlock1Ptr->lastHealLocation, healLocation->group, healLocation->map, -1, healLocation->x, healLocation->y); +} + +void UpdateEscapeWarp(s16 x, s16 y) +{ + u8 currMapType = GetCurrentMapType(); + u8 destMapType = GetMapTypeByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); + u8 delta; + if (IsMapTypeOutdoors(currMapType) && IsMapTypeOutdoors(destMapType) != TRUE && !(gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(VIRIDIAN_FOREST) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(VIRIDIAN_FOREST))) + { + delta = GetPlayerFacingDirection() != DIR_SOUTH; + SetEscapeWarp(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, x - 7, y - 7 + delta); + } +} + +void SetEscapeWarp(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->escapeWarp, mapGroup, mapNum, warpId, x, y); +} + +void SetWarpDestinationToEscapeWarp(void) +{ + sWarpDestination = gSaveBlock1Ptr->escapeWarp; +} + +void SetFixedDiveWarp(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gFixedDiveWarp, mapGroup, mapNum, warpId, x, y); +} + +void SetWarpDestinationToDiveWarp(void) +{ + sWarpDestination = gFixedDiveWarp; +} + +void SetFixedHoleWarp(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gFixedHoleWarp, mapGroup, mapNum, warpId, x, y); +} + +void SetWarpDestinationToFixedHoleWarp(s16 x, s16 y) +{ + if (IsDummyWarp(&gFixedHoleWarp) == TRUE) + sWarpDestination = gLastUsedWarp; + else + SetWarpDestination(gFixedHoleWarp.mapGroup, gFixedHoleWarp.mapNum, -1, x, y); +} + +void SetWarpDestinationToContinueGameWarp(void) +{ + sWarpDestination = gSaveBlock1Ptr->continueGameWarp; +} + +void SetContinueGameWarp(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->continueGameWarp, mapGroup, mapNum, warpId, x, y); +} + +void SetContinueGameWarpToHealLocation(u8 healLocationId) +{ + const struct HealLocation *warp = GetHealLocation(healLocationId); + if (warp) + SetWarpData(&gSaveBlock1Ptr->continueGameWarp, warp->group, warp->map, -1, warp->x, warp->y); +} + +void SetContinueGameWarpToDynamicWarp(int unused) +{ + gSaveBlock1Ptr->continueGameWarp = gSaveBlock1Ptr->dynamicWarp; +} + +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 SetDiveWarp(u8 dir, u16 x, u16 y) +{ + const struct MapConnection *connection = GetMapConnection(dir); + + if (connection != NULL) + { + SetWarpDestination(connection->mapGroup, connection->mapNum, -1, x, y); + } + else + { + RunOnDiveWarpMapScript(); + if (IsDummyWarp(&gFixedDiveWarp)) + return FALSE; + SetWarpDestinationToDiveWarp(); + } + return TRUE; +} + +bool8 SetDiveWarpEmerge(u16 x, u16 y) +{ + return SetDiveWarp(CONNECTION_EMERGE, x, y); +} + +bool8 SetDiveWarpDive(u16 x, u16 y) +{ + return SetDiveWarp(CONNECTION_DIVE, x, y); +} + +// Map loaders + +void LoadMapFromCameraTransition(u8 mapGroup, u8 mapNum) +{ + int paletteIndex; + + SetWarpDestination(mapGroup, mapNum, -1, -1, -1); + Overworld_TryMapConnectionMusicTransition(); + ApplyCurrentWarp(); + LoadCurrentMapData(); + sub_8054F68(); + TrySetMapSaveWarpStatus(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + RestartWildEncounterImmunitySteps(); + TryUpdateRandomTrainerRematches(mapGroup, mapNum); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + RunOnTransitionMapScript(); + TryRegenerateRenewableHiddenItems(); + InitMap(); + copy_map_tileset2_to_vram_2(gMapHeader.mapLayout); + apply_map_tileset2_palette(gMapHeader.mapLayout); + for (paletteIndex = 7; paletteIndex < 13; paletteIndex++) + ApplyWeatherGammaShiftToPal(paletteIndex); + InitSecondaryTilesetAnimation(); + UpdateLocationHistoryForRoamer(); + RoamerMove(); + sub_8110920(); + DoCurrentWeather(); + ResetFieldTasksArgs(); + RunOnResumeMapScript(); + if (GetLastUsedWarpMapSectionId() != gMapHeader.regionMapSectionId) + ShowMapNamePopup(TRUE); +} + +void mli0_load_map(bool32 a1) +{ + bool8 isOutdoors; + + LoadCurrentMapData(); + sub_8054F68(); + isOutdoors = IsMapTypeOutdoors(gMapHeader.mapType); + + TrySetMapSaveWarpStatus(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + RestartWildEncounterImmunitySteps(); + TryUpdateRandomTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + if (isOutdoors) + FlagClear(FLAG_SYS_FLASH_ACTIVE); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + RunOnTransitionMapScript(); + TryRegenerateRenewableHiddenItems(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); + sub_8110920(); + InitMap(); +} + +void sub_80559A8(void) +{ + bool8 isOutdoors; + + LoadCurrentMapData(); + sub_8054F68(); + isOutdoors = IsMapTypeOutdoors(gMapHeader.mapType); + TrySetMapSaveWarpStatus(); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + SetDefaultFlashLevel(); + sub_8110920(); + sub_8111708(); + LoadSaveblockMapHeader(); + InitMap(); +} + +// Routines related to the initial player avatar state + +void ResetInitialPlayerAvatarState(void) +{ + gInitialPlayerAvatarState.direction = DIR_SOUTH; + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_ON_FOOT; + gInitialPlayerAvatarState.unk2 = FALSE; +} + +void SetInitialPlayerAvatarStateWithDirection(u8 dirn) +{ + gInitialPlayerAvatarState.direction = dirn; + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_ON_FOOT; + gInitialPlayerAvatarState.unk2 = TRUE; +} + +void StoreInitialPlayerAvatarState(void) +{ + gInitialPlayerAvatarState.direction = GetPlayerFacingDirection(); + + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE)) + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_MACH_BIKE; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_ACRO_BIKE)) + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_ACRO_BIKE; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_SURFING; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_UNDERWATER)) + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_UNDERWATER; + else + gInitialPlayerAvatarState.transitionFlags = PLAYER_AVATAR_FLAG_ON_FOOT; + gInitialPlayerAvatarState.unk2 = FALSE; +} + +struct InitialPlayerAvatarState *GetInitialPlayerAvatarState(void) +{ + struct InitialPlayerAvatarState playerStruct; + u8 mapType = GetCurrentMapType(); + u16 metatileBehavior = GetCenterScreenMetatileBehavior(); + u8 transitionFlags = GetAdjustedInitialTransitionFlags(&gInitialPlayerAvatarState, metatileBehavior, mapType); + playerStruct.transitionFlags = transitionFlags; + playerStruct.direction = GetAdjustedInitialDirection(&gInitialPlayerAvatarState, transitionFlags, metatileBehavior, mapType); + playerStruct.unk2 = FALSE; + gInitialPlayerAvatarState = playerStruct; + return &gInitialPlayerAvatarState; +} + +u8 GetAdjustedInitialTransitionFlags(struct InitialPlayerAvatarState *playerStruct, u16 metatileBehavior, u8 mapType) +{ + if (mapType != MAP_TYPE_INDOOR && FlagGet(FLAG_SYS_CRUISE_MODE)) + return PLAYER_AVATAR_FLAG_ON_FOOT; + else if (mapType == MAP_TYPE_UNDERWATER) + return PLAYER_AVATAR_FLAG_UNDERWATER; + else if (sub_8055B38(metatileBehavior) == TRUE) + return PLAYER_AVATAR_FLAG_ON_FOOT; + else if (MetatileBehavior_IsSurfable(metatileBehavior) == TRUE) + return PLAYER_AVATAR_FLAG_SURFING; + else if (Overworld_IsBikingAllowed() != TRUE) + return PLAYER_AVATAR_FLAG_ON_FOOT; + else if (playerStruct->transitionFlags == PLAYER_AVATAR_FLAG_MACH_BIKE) + return PLAYER_AVATAR_FLAG_MACH_BIKE; + else if (playerStruct->transitionFlags != PLAYER_AVATAR_FLAG_ACRO_BIKE) + return PLAYER_AVATAR_FLAG_ON_FOOT; + else + return PLAYER_AVATAR_FLAG_ACRO_BIKE; +} + +bool8 sub_8055B38(u16 metatileBehavior) +{ + if (MetatileBehavior_IsSurfable(metatileBehavior) != TRUE) + return FALSE; + if ((gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(SEAFOAM_ISLANDS_B3F) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(SEAFOAM_ISLANDS_B3F)) || (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(SEAFOAM_ISLANDS_B4F) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(SEAFOAM_ISLANDS_B4F))) + return TRUE; + return FALSE; +} + +u8 GetAdjustedInitialDirection(struct InitialPlayerAvatarState *playerStruct, u8 transitionFlags, u16 metatileBehavior, u8 mapType) +{ + if (FlagGet(FLAG_SYS_CRUISE_MODE) && mapType == MAP_TYPE_OCEAN_ROUTE) + return DIR_EAST; + else if (MetatileBehavior_IsDeepSouthWarp(metatileBehavior) == TRUE) + return DIR_NORTH; + else if (MetatileBehavior_IsNonAnimDoor(metatileBehavior) == TRUE || MetatileBehavior_IsWarpDoor_2(metatileBehavior) == TRUE) + return DIR_SOUTH; + else if (MetatileBehavior_IsSouthArrowWarp(metatileBehavior) == TRUE) + return DIR_NORTH; + else if (MetatileBehavior_IsNorthArrowWarp(metatileBehavior) == TRUE) + return DIR_SOUTH; + else if (MetatileBehavior_IsWestArrowWarp(metatileBehavior) == TRUE) + return DIR_EAST; + else if (MetatileBehavior_IsEastArrowWarp(metatileBehavior) == TRUE) + return DIR_WEST; + else if (MetatileBehavior_IsUnknownWarp6C(metatileBehavior) == TRUE || MetatileBehavior_IsUnknownWarp6E(metatileBehavior) == TRUE) + return DIR_WEST; + else if (MetatileBehavior_IsUnknownWarp6D(metatileBehavior) == TRUE || MetatileBehavior_IsUnknownWarp6F(metatileBehavior) == TRUE) + return DIR_EAST; + else if ((playerStruct->transitionFlags == PLAYER_AVATAR_FLAG_UNDERWATER && transitionFlags == PLAYER_AVATAR_FLAG_SURFING) + || (playerStruct->transitionFlags == PLAYER_AVATAR_FLAG_SURFING && transitionFlags == PLAYER_AVATAR_FLAG_UNDERWATER )) + return playerStruct->direction; + else if (MetatileBehavior_IsLadder(metatileBehavior) == TRUE) + return playerStruct->direction; + else if (playerStruct->unk2) + return playerStruct->direction; + else + return DIR_SOUTH; +} + +u16 GetCenterScreenMetatileBehavior(void) +{ + return MapGridGetMetatileBehaviorAt(gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7); +} + +// Routines related to flash level and map perms + +bool32 Overworld_IsBikingAllowed(void) +{ + if (!gMapHeader.bikingAllowed) + return FALSE; + else + return TRUE; +} + +void SetDefaultFlashLevel(void) +{ + if (!gMapHeader.cave) + gSaveBlock1Ptr->flashLevel = 0; + else if (FlagGet(FLAG_SYS_FLASH_ACTIVE)) + gSaveBlock1Ptr->flashLevel = 0; + else + gSaveBlock1Ptr->flashLevel = gMaxFlashLevel; +} + +void Overworld_SetFlashLevel(s32 flashLevel) +{ + if (flashLevel < 0 || flashLevel > gMaxFlashLevel) + flashLevel = 0; + gSaveBlock1Ptr->flashLevel = flashLevel; +} + +u8 Overworld_GetFlashLevel(void) +{ + return gSaveBlock1Ptr->flashLevel; +} + +void SetCurrentMapLayout(u16 mapLayoutId) +{ + gSaveBlock1Ptr->mapLayoutId = mapLayoutId; + gMapHeader.mapLayout = GetMapLayout(); +} + +void sub_8055D5C(struct WarpData * warp) +{ + sWarpDestination = *warp; +} + +// Routines related to map music + +u16 GetLocationMusic(struct WarpData * warp) +{ + return Overworld_GetMapHeaderByGroupAndId(warp->mapGroup, warp->mapNum)->music; +} + +u16 GetCurrLocationDefaultMusic(void) +{ + u16 music; + music = GetLocationMusic(&gSaveBlock1Ptr->location); + return music; +} + +u16 GetWarpDestinationMusic(void) +{ + u16 music = GetLocationMusic(&sWarpDestination); + return music; +} + +void Overworld_ResetMapMusic(void) +{ + ResetMapMusic(); +} + +void Overworld_PlaySpecialMapMusic(void) +{ + u16 music; + s16 x, y; + + if (gDisableMapMusicChangeOnMapLoad == 1) + { + StopMapMusic(); + return; + } + if (gDisableMapMusicChangeOnMapLoad == 2) + { + return; + } + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(POKEMON_LEAGUE_CHAMPIONS_ROOM) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(POKEMON_LEAGUE_CHAMPIONS_ROOM)) + { + PlayerGetDestCoords(&x, &y); + if (y - 7 < 11 && gMPlayInfo_BGM.songHeader == &mus_win_gym) + { + FadeInBGM(4); + return; + } + } + + music = GetCurrLocationDefaultMusic(); + + if (gSaveBlock1Ptr->savedMusic) + music = gSaveBlock1Ptr->savedMusic; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING) &&sub_8056124(MUS_NAMINORI)) + music = MUS_NAMINORI; + + if (music != GetCurrentMapMusic()) + PlayNewMapMusic(music); +} + +void Overworld_SetSavedMusic(u16 songNum) +{ + gSaveBlock1Ptr->savedMusic = songNum; +} + +void Overworld_ClearSavedMusic(void) +{ + gSaveBlock1Ptr->savedMusic = 0; +} + +void Overworld_TryMapConnectionMusicTransition(void) +{ + u16 newMusic; + u16 currentMusic; + + if (gDisableMapMusicChangeOnMapLoad == 1) + { + StopMapMusic(); + return; + } + if (gDisableMapMusicChangeOnMapLoad == 2) + { + return; + } + + if (FlagGet(FLAG_DONT_TRANSITION_MUSIC) != TRUE) + { + newMusic = GetWarpDestinationMusic(); + currentMusic = GetCurrentMapMusic(); + if (currentMusic == MUS_NAMINORI) + return; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING) && sub_8056124(MUS_NAMINORI)) + 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) + FadeOutAndPlayNewMapMusic(newMusic, 8); +} + +u8 GetMapMusicFadeoutSpeed(void) +{ + const struct MapHeader *mapHeader = GetDestinationWarpMapHeader(); + if (IsMapTypeIndoors(mapHeader->mapType) == TRUE) + return 2; + else + return 4; +} + +void TryFadeOutOldMapMusic(void) +{ + u16 warpMusic = GetWarpDestinationMusic(); + if (FlagGet(FLAG_DONT_TRANSITION_MUSIC) != TRUE && warpMusic != GetCurrentMapMusic()) + { + FadeOutMapMusic(GetMapMusicFadeoutSpeed()); + } +} + +bool8 BGMusicStopped(void) +{ + return IsNotWaitingForBGMStop(); +} + +void Overworld_FadeOutMapMusic(void) +{ + FadeOutMapMusic(4); +} + +void PlayAmbientCry(void) +{ + s16 x, y; + s8 pan; + s8 volume; + + PlayerGetDestCoords(&x, &y); + if (sIsAmbientCryWaterMon == TRUE + && !MetatileBehavior_IsSurfable(MapGridGetMetatileBehaviorAt(x, y))) + return; + pan = (Random() % 88) + 212; + volume = (Random() % 30) + 50; + + if (gDisableMapMusicChangeOnMapLoad == 1) + { + StopMapMusic(); + return; + } + if (gDisableMapMusicChangeOnMapLoad == 2) + { + return; + } + + 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: + *delayCounter = (Random() % 1200) + 1200; + *state = 3; + break; + case 3: + (*delayCounter)--; + if (*delayCounter == 0) + { + PlayAmbientCry(); + *state = 2; + } + break; + case 4: + break; + } +} + +void ChooseAmbientCrySpecies(void) +{ + sAmbientCrySpecies = GetLocalWildMon(&sIsAmbientCryWaterMon); +} + +bool32 sub_8056124(u16 music) +{ + if (music == MUS_CYCLING || music == MUS_NAMINORI) + { + if (gMapHeader.regionMapSectionId == MAPSEC_KANTO_VICTORY_ROAD || gMapHeader.regionMapSectionId == MAPSEC_ROUTE_23 || gMapHeader.regionMapSectionId == MAPSEC_INDIGO_PLATEAU) + return FALSE; + } + return TRUE; +} + +u8 GetMapTypeByGroupAndId(s8 mapGroup, s8 mapNum) +{ + return Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum)->mapType; +} + +u8 GetMapTypeByWarpData(struct WarpData *warp) +{ + return GetMapTypeByGroupAndId(warp->mapGroup, warp->mapNum); +} + +u8 GetCurrentMapType(void) +{ + return GetMapTypeByWarpData(&gSaveBlock1Ptr->location); +} + +u8 GetLastUsedWarpMapType(void) +{ + return GetMapTypeByWarpData(&gLastUsedWarp); +} + +u8 GetLastUsedWarpMapSectionId(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gLastUsedWarp.mapGroup, gLastUsedWarp.mapNum)->regionMapSectionId; +} + +bool8 IsMapTypeOutdoors(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_UNDERWATER + || mapType == MAP_TYPE_CITY + || mapType == MAP_TYPE_OCEAN_ROUTE) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeAllowsTeleportAndFly(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_OCEAN_ROUTE + || mapType == MAP_TYPE_CITY) + return TRUE; + else + return FALSE; +} + +bool8 IsMapTypeIndoors(u8 mapType) +{ + if (mapType == MAP_TYPE_INDOOR + || mapType == MAP_TYPE_SECRET_BASE) + return TRUE; + else + return FALSE; +} + +u8 GetSavedWarpRegionMapSectionId(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->dynamicWarp.mapGroup, gSaveBlock1Ptr->dynamicWarp.mapNum)->regionMapSectionId; +} + +u8 GetCurrentRegionMapSectionId(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)->regionMapSectionId; +} + +u8 GetCurrentMapBattleScene(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)->battleType; +} + +const int sUnusedData[] = { + 1200, + 3600, + 1200, + 2400, + 50, + 80, + -44, + 44 +}; + +const struct UCoords32 gDirectionToVectors[] = { + { 0u, 0u}, + { 0u, 1u}, + { 0u, -1u}, + {-1u, 0u}, + { 1u, 0u}, + {-1u, 1u}, + { 1u, 1u}, + {-1u, -1u}, + { 1u, -1u}, +}; + +const struct BgTemplate sOverworldBgTemplates[] = { + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0x000 + }, { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 29, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0x000 + }, { + .bg = 2, + .charBaseIndex = 0, + .mapBaseIndex = 28, + .screenSize = 0, + .paletteMode = 0, + .priority = 2, + .baseTile = 0x000 + }, { + .bg = 3, + .charBaseIndex = 0, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0x000 + } +}; + +void InitOverworldBgs(void) +{ + MoveSaveBlocks_ResetHeap_(); + sub_8056E80(); + ResetBgsAndClearDma3BusyFlags(FALSE); + InitBgsFromTemplates(0, sOverworldBgTemplates, NELEMS(sOverworldBgTemplates)); + SetBgAttribute(1, BG_ATTR_MOSAIC, TRUE); + SetBgAttribute(2, BG_ATTR_MOSAIC, TRUE); + SetBgAttribute(3, BG_ATTR_MOSAIC, TRUE); + gBGTilemapBuffers2 = AllocZeroed(BG_SCREEN_SIZE); + gBGTilemapBuffers1 = AllocZeroed(BG_SCREEN_SIZE); + gBGTilemapBuffers3 = AllocZeroed(BG_SCREEN_SIZE); + SetBgTilemapBuffer(1, gBGTilemapBuffers2); + SetBgTilemapBuffer(2, gBGTilemapBuffers1); + SetBgTilemapBuffer(3, gBGTilemapBuffers3); + InitStandardTextBoxWindows(); + ResetBg0(); + sub_8069348(); +} + +void InitOverworldBgs_NoResetHeap(void) +{ + ResetBgsAndClearDma3BusyFlags(FALSE); + InitBgsFromTemplates(0, sOverworldBgTemplates, NELEMS(sOverworldBgTemplates)); + SetBgAttribute(1, BG_ATTR_MOSAIC, TRUE); + SetBgAttribute(2, BG_ATTR_MOSAIC, TRUE); + SetBgAttribute(3, BG_ATTR_MOSAIC, TRUE); + gBGTilemapBuffers2 = AllocZeroed(BG_SCREEN_SIZE); + gBGTilemapBuffers1 = AllocZeroed(BG_SCREEN_SIZE); + gBGTilemapBuffers3 = AllocZeroed(BG_SCREEN_SIZE); + SetBgTilemapBuffer(1, gBGTilemapBuffers2); + SetBgTilemapBuffer(2, gBGTilemapBuffers1); + SetBgTilemapBuffer(3, gBGTilemapBuffers3); + InitStandardTextBoxWindows(); + ResetBg0(); + sub_8069348(); +} + +void CleanupOverworldWindowsAndTilemaps(void) +{ + FreeAllOverworldWindowBuffers(); + Free(gBGTilemapBuffers3); + Free(gBGTilemapBuffers1); + Free(gBGTilemapBuffers2); +} + +void ResetSafariZoneFlag_(void) +{ + ResetSafariZoneFlag(); +} + +bool32 IsUpdateLinkStateCBActive(void) +{ + if (gMain.callback1 == CB1_UpdateLinkState) + return TRUE; + else + return FALSE; +} + +void DoCB1_Overworld(u16 newKeys, u16 heldKeys) +{ + struct FieldInput fieldInput; + + sub_8112B3C(); + sub_805BEB8(); + FieldClearPlayerInput(&fieldInput); + FieldGetPlayerInput(&fieldInput, newKeys, heldKeys); + FieldInput_HandleCancelSignpost(&fieldInput); + if (!ScriptContext2_IsEnabled()) + { + if (ProcessPlayerFieldInput(&fieldInput) == TRUE) + { + if (gUnknown_3005E88 == 2) + sub_81127F8(&gInputToStoreInQuestLogMaybe); + ScriptContext2_Enable(); + DismissMapNamePopup(); + } + else + { + player_step(fieldInput.dpadDirection, newKeys, heldKeys); + } + } + RunQuestLogCB(); +} + +void DoCB1_Overworld_QuestLogPlayback(void) +{ + struct FieldInput fieldInput; + + sub_8112B3C(); + sub_805BEB8(); + sub_8111C68(); + FieldClearPlayerInput(&fieldInput); + fieldInput = gUnknown_3005E90; + FieldInput_HandleCancelSignpost(&fieldInput); + if (!ScriptContext2_IsEnabled()) + { + if (ProcessPlayerFieldInput(&fieldInput) == TRUE) + { + ScriptContext2_Enable(); + DismissMapNamePopup(); + } + else + { + RunQuestLogCB(); + } + } + else if (sub_8111CD0() == TRUE) + { + RunQuestLogCB(); + } + FieldClearPlayerInput(&gUnknown_3005E90); +} + +void CB1_Overworld(void) +{ + if (gMain.callback2 == CB2_Overworld) + { + if (sub_8112CAC() == TRUE || gQuestLogState == QL_STATE_2) + DoCB1_Overworld_QuestLogPlayback(); + else + DoCB1_Overworld(gMain.newKeys, gMain.heldKeys); + } +} + +void OverworldBasic(void) +{ + ScriptContext2_RunScript(); + RunTasks(); + AnimateSprites(); + CameraUpdate(); + sub_8115798(); + UpdateCameraPanning(); + BuildOamBuffer(); + UpdatePaletteFade(); + UpdateTilesetAnimations(); + DoScheduledBgTilemapCopiesToVram(); +} + +// This CB2 is used when starting +void CB2_OverworldBasic(void) +{ + OverworldBasic(); +} + +void CB2_Overworld(void) +{ + bool32 fading = !!gPaletteFade.active; + if (fading) + SetVBlankCallback(NULL); + OverworldBasic(); + if (fading) + SetFieldVBlankCallback(); +} + +void SetMainCallback1(MainCallback cb) +{ + gMain.callback1 = cb; +} + +bool8 map_post_load_hook_exec(void) +{ + if (gFieldCallback2) + { + if (!gFieldCallback2()) + { + return FALSE; + } + else + { + gFieldCallback2 = NULL; + gFieldCallback = NULL; + } + } + else + { + if (gFieldCallback) + gFieldCallback(); + else + FieldCB_DefaultWarpExit(); + + gFieldCallback = NULL; + } + + return TRUE; +} + +void CB2_NewGame(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + NewGameInitData(); + ResetInitialPlayerAvatarState(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = FieldCB_WarpExitFadeFromBlack; + gFieldCallback2 = 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(); + SetInitialPlayerAvatarStateWithDirection(DIR_NORTH); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = FieldCB_RushInjuredPokemonToCenter; + val = 0; + do_load_map_stuff_loop(&val); + sub_8112364(); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_LoadMap(void) +{ + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + SetMainCallback2(CB2_DoChangeMap); + gMain.savedCallback = CB2_LoadMap2; +} + +void CB2_LoadMap2(void) +{ + do_load_map_stuff_loop(&gMain.state); + if (sub_8113748() == TRUE) + { + sub_81119C8(); + } + else + { + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToFieldCableClub(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = FieldCB_ReturnToFieldWirelessLink; + SetMainCallback2(c2_80567AC); +} + +void c2_80567AC(void) +{ + if (map_loading_iteration_3(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback1(CB1_UpdateLinkState); + ResetAllMultiplayerState(); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToField(void) +{ + if (IsUpdateLinkStateCBActive() == TRUE) + { + SetMainCallback2(CB2_ReturnToFieldLink); + } + else + { + FieldClearVBlankHBlankCallbacks(); + SetMainCallback2(CB2_ReturnToFieldLocal); + } +} + +void CB2_ReturnToFieldLocal(void) +{ + if (sub_8056CD8(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToFieldLink(void) +{ + if (!sub_8058244() && map_loading_iteration_2_link(&gMain.state)) + SetMainCallback2(CB2_Overworld); +} + +void CB2_ReturnToFieldFromMultiplayer(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + SetMainCallback1(CB1_UpdateLinkState); + ResetAllMultiplayerState(); + + if (gWirelessCommType != 0) + gFieldCallback = FieldCB_ReturnToFieldWirelessLink; + else + gFieldCallback = FieldCB_ReturnToFieldCableLink; + + ScriptContext1_Init(); + ScriptContext2_Disable(); + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldWithOpenMenu(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback2 = FieldCB_ReturnToFieldOpenStartMenu; + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldContinueScript(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = FieldCB_ContinueScript; + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldContinueScriptPlayMapMusic(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = FieldCB_ContinueScriptHandleMusic; + CB2_ReturnToField(); +} + +void sub_80568FC(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = FieldCB_WarpExitFadeFromBlack; + CB2_ReturnToField(); +} + +void sub_8056918(void) +{ + if (SHOW_MAP_NAME_ENABLED) + ShowMapNamePopup(FALSE); + FieldCB_WarpExitFadeFromBlack(); +} + +void CB2_ContinueSavedGame(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + LoadSaveblockMapHeader(); + LoadSaveblockObjEventScripts(); + UnfreezeObjectEvents(); + sub_8054E40(); + InitMapFromSavedGame(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback2 = NULL; + gUnknown_2031DE0 = TRUE; + if (UseContinueGameWarp() == TRUE) + { + ClearContinueGameWarpStatus(); + SetWarpDestinationToContinueGameWarp(); + WarpIntoMap(); + SetMainCallback2(CB2_LoadMap); + } + else + { + gFieldCallback = sub_8056918; + SetMainCallback1(CB1_Overworld); + CB2_ReturnToField(); + } +} + +void FieldClearVBlankHBlankCallbacks(void) +{ + if (UsedPokemonCenterWarp() == TRUE) + CloseLink(); + + if (gWirelessCommType != 0) + { + EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + DisableInterrupts(INTR_FLAG_HBLANK); + } + else + { + DisableInterrupts(INTR_FLAG_HBLANK); + EnableInterrupts(INTR_FLAG_VBLANK); + } + + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +void SetFieldVBlankCallback(void) +{ + SetVBlankCallback(VBlankCB_Field); +} + +void VBlankCB_Field(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + ScanlineEffect_InitHBlankDmaTransfer(); + FieldUpdateBgTilemapScroll(); + TransferPlttBuffer(); + TransferTilesetAnimsBuffer(); +} + +void InitCurrentFlashLevelScanlineEffect(void) +{ + u8 flashLevel = Overworld_GetFlashLevel(); + if (flashLevel != 0) + { + WriteFlashScanlineEffectBuffer(flashLevel); + ScanlineEffect_SetParams((struct ScanlineEffectParams){ + .dmaDest = ®_WIN0H, + .dmaControl = (2 >> 1) | ((DMA_16BIT | DMA_DEST_RELOAD | DMA_SRC_INC | DMA_REPEAT | DMA_START_HBLANK | DMA_ENABLE) << 16), + .initState = 1, + .unused9 = 0 + }); + } +} + +bool32 map_loading_iteration_3(u8 *state) +{ + switch (*state) + { + case 0: + InitOverworldBgs(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + (*state)++; + break; + case 1: + mli0_load_map(TRUE); + (*state)++; + break; + case 2: + sub_8057024(TRUE); + (*state)++; + break; + case 3: + sub_8057178(); + sub_8057074(); + sub_80571A8(); + SetCameraToTrackGuestPlayer(); + SetHelpContextForMap(); + (*state)++; + break; + case 4: + InitCurrentFlashLevelScanlineEffect(); + InitOverworldGraphicsRegisters(); + (*state)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 6: + copy_map_tileset1_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 7: + copy_map_tileset2_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 8: + if (FreeTempTileDataBuffersIfPossible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapLayout); + (*state)++; + } + break; + case 9: + DrawWholeMapView(); + (*state)++; + break; + case 10: + InitTilesetAnimations(); + (*state)++; + break; + case 11: + if (gWirelessCommType != 0) + { + LoadWirelessStatusIndicatorSpriteGfx(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 13: + return TRUE; + } + + return FALSE; +} + +bool32 load_map_stuff(u8 *state, bool32 a1) +{ + switch (*state) + { + case 0: + InitOverworldBgs(); + FieldClearVBlankHBlankCallbacks(); + mli0_load_map(a1); + (*state)++; + break; + case 1: + sub_8111F14(); + (*state)++; + break; + case 2: + sub_8057024(a1); + (*state)++; + break; + case 3: + if (sub_8113748() == TRUE) + return TRUE; + (*state)++; + break; + case 4: + mli4_mapscripts_and_other(); + sub_8057114(); + if (gQuestLogState != QL_STATE_2) + { + sub_80CC534(); + sub_80CC59C(); + } + SetHelpContextForMap(); + (*state)++; + break; + case 5: + InitCurrentFlashLevelScanlineEffect(); + InitOverworldGraphicsRegisters(); + (*state)++; + break; + case 6: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 7: + copy_map_tileset1_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 8: + copy_map_tileset2_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 9: + if (FreeTempTileDataBuffersIfPossible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapLayout); + (*state)++; + } + break; + case 10: + DrawWholeMapView(); + (*state)++; + break; + case 11: + InitTilesetAnimations(); + (*state)++; + break; + case 12: + if (GetLastUsedWarpMapSectionId() != gMapHeader.regionMapSectionId && MapHasPreviewScreen_HandleQLState2(gMapHeader.regionMapSectionId, MPS_TYPE_FOREST) == TRUE) + { + MapPreview_LoadGfx(gMapHeader.regionMapSectionId); + MapPreview_StartForestTransition(gMapHeader.regionMapSectionId); + } + else if (SHOW_MAP_NAME_ENABLED) + { + ShowMapNamePopup(FALSE); + } + (*state)++; + break; + case 13: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 14: + return TRUE; + } + return FALSE; +} + +bool32 sub_8056CD8(u8 *state) +{ + switch (*state) + { + case 0: + InitOverworldBgs(); + sub_8111F14(); + sub_8057024(FALSE); + sub_8057100(); + sub_8057114(); + (*state)++; + break; + case 1: + (*state)++; + break; + case 2: + sub_8056F08(); + SetHelpContextForMap(); + (*state)++; + break; + case 3: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 4: + return TRUE; + } + return FALSE; +} + +bool32 map_loading_iteration_2_link(u8 *state) +{ + switch (*state) + { + case 0: + InitOverworldBgs(); + FieldClearVBlankHBlankCallbacks(); + (*state)++; + break; + case 1: + sub_8111F14(); + sub_8057024(1); + (*state)++; + break; + case 2: + CreateLinkPlayerSprites(); + sub_8057100(); + SetCameraToTrackGuestPlayer_2(); + SetHelpContextForMap(); + (*state)++; + break; + case 3: + InitCurrentFlashLevelScanlineEffect(); + InitOverworldGraphicsRegisters(); + (*state)++; + break; + case 4: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 5: + copy_map_tileset1_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 6: + copy_map_tileset2_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 7: + if (FreeTempTileDataBuffersIfPossible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapLayout); + (*state)++; + } + break; + case 8: + DrawWholeMapView(); + (*state)++; + break; + case 9: + InitTilesetAnimations(); + (*state)++; + break; + case 10: + (*state)++; + break; + case 11: + if (gWirelessCommType != 0) + { + LoadWirelessStatusIndicatorSpriteGfx(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 13: + SetFieldVBlankCallback(); + (*state)++; + return TRUE; + } + + return FALSE; +} + +void do_load_map_stuff_loop(u8 *state) +{ + while (!load_map_stuff(state, FALSE)) + ; +} + +void MoveSaveBlocks_ResetHeap_(void) +{ + MoveSaveBlocks_ResetHeap(); +} + +void sub_8056E80(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(); +} + +void sub_8056F08(void) +{ + InitCurrentFlashLevelScanlineEffect(); + InitOverworldGraphicsRegisters(); + mapdata_load_assets_to_gpu_and_full_redraw(); +} + +void InitOverworldGraphicsRegisters(void) +{ + ClearScheduledBgCopiesToVram(); + ResetTempTileDataBuffers(); + SetGpuReg(REG_OFFSET_MOSAIC, 0); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG0 | WINOUT_WINOBJ_BG0); + SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, 255)); + SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(0, 255)); + SetGpuReg(REG_OFFSET_WIN1H, WIN_RANGE(255, 255)); + SetGpuReg(REG_OFFSET_WIN1V, WIN_RANGE(255, 255)); + SetGpuReg(REG_OFFSET_BLDCNT, gOverworldBackgroundLayerFlags[1] | gOverworldBackgroundLayerFlags[2] | gOverworldBackgroundLayerFlags[3] + | BLDCNT_TGT2_OBJ | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(13, 7)); + ScheduleBgCopyTilemapToVram(1); + ScheduleBgCopyTilemapToVram(2); + ScheduleBgCopyTilemapToVram(3); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | 0x20 | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON); + ShowBg(0); + ShowBg(1); + ShowBg(2); + ShowBg(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); +} + +void sub_8057024(u32 a1) +{ + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + ScanlineEffect_Clear(); + ResetAllPicSprites(); + ResetCameraUpdateInfo(); + InstallCameraPanAheadCallback(); + if (!a1) + InitObjectEventPalettes(0); + else + InitObjectEventPalettes(1); + + FieldEffectActiveListClear(); + StartWeather(); + ResumePausedWeather(); + if (!a1) + SetUpFieldTasks(); + RunOnResumeMapScript(); +} + +void sub_8057074(void) +{ + gTotalCameraPixelOffsetX = 0; + gTotalCameraPixelOffsetY = 0; + ResetObjectEvents(); + TrySpawnObjectEvents(0, 0); + TryRunOnWarpIntoMapScript(); +} + +void mli4_mapscripts_and_other(void) +{ + s16 x, y; + struct InitialPlayerAvatarState *player; + + gTotalCameraPixelOffsetX = 0; + gTotalCameraPixelOffsetY = 0; + ResetObjectEvents(); + GetCameraFocusCoords(&x, &y); + player = GetInitialPlayerAvatarState(); + InitPlayerAvatar(x, y, player->direction, gSaveBlock2Ptr->playerGender); + SetPlayerAvatarTransitionFlags(player->transitionFlags); + ResetInitialPlayerAvatarState(); + TrySpawnObjectEvents(0, 0); + TryRunOnWarpIntoMapScript(); +} + +void sub_8057100(void) +{ + sub_805EDF0(0, 0); + RunOnReturnToFieldMapScript(); +} + +void sub_8057114(void) +{ + gObjectEvents[gPlayerAvatar.objectEventId].trackedByCamera = 1; + InitCameraUpdateCallback(gPlayerAvatar.spriteId); +} + +void SetCameraToTrackGuestPlayer(void) +{ + InitCameraUpdateCallback(GetSpriteForLinkedPlayer(gLocalLinkPlayerId)); +} + +// Duplicate function. +void SetCameraToTrackGuestPlayer_2(void) +{ + InitCameraUpdateCallback(GetSpriteForLinkedPlayer(gLocalLinkPlayerId)); +} + +void sub_8057178(void) +{ + u16 x, y; + GetCameraFocusCoords(&x, &y); + + // This is a hack of some kind; it's undone in sub_8086B14, which is called + // soon after this function. + SetCameraFocusCoords(x + gLocalLinkPlayerId, y); +} + +void sub_80571A8(void) +{ + u16 i; + u16 x, y; + + GetCameraFocusCoords(&x, &y); + x -= gLocalLinkPlayerId; + + for (i = 0; i < gFieldLinkPlayerCount; i++) + { + SpawnLinkPlayerObjectEvent(i, i + x, y, gLinkPlayers[i].gender); + CreateLinkPlayerSprite(i, gLinkPlayers[i].version); + } + + ClearAllPlayerKeys(); +} + +void CreateLinkPlayerSprites(void) +{ + u16 i; + for (i = 0; i < gFieldLinkPlayerCount; i++) + CreateLinkPlayerSprite(i, gLinkPlayers[i].version); +} + +// Credits + +void sub_805726C(void) +{ + FieldClearVBlankHBlankCallbacks(); + gUnknown_2036E28 = 1; + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + SetMainCallback2(CB2_DoChangeMap); + gMain.savedCallback = sub_80572D8; +} + +void sub_80572A8(void) +{ + FieldClearVBlankHBlankCallbacks(); + gUnknown_2036E28 = 1; + LoadSaveblockMapHeader(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + SetMainCallback2(sub_80572D8); +} + +void sub_80572D8(void) +{ + sub_8057300(&gMain.state); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); +} + +void sub_8057300(u8 *state) +{ + while (!sub_8057314(state)) + ; +} + +bool32 sub_8057314(u8 *state) +{ + switch (*state) + { + case 0: + InitOverworldBgs(); + FieldClearVBlankHBlankCallbacks(); + sub_8111F14(); + sub_81113E4(); + sub_8111438(); + if (sub_8110AC8() == 2) + { + gUnknown_2031DE0 = 0; + mli0_load_map(FALSE); + } + else + { + gUnknown_2031DE0 = 1; + sub_80559A8(); + } + (*state)++; + break; + case 1: + sub_8110FCC(); + (*state)++; + break; + case 2: + sub_8057024(0); + (*state)++; + break; + case 3: + sub_8057100(); + sub_8057114(); + (*state)++; + break; + case 4: + InitCurrentFlashLevelScanlineEffect(); + InitOverworldGraphicsRegisters(); + (*state)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 6: + copy_map_tileset1_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 7: + copy_map_tileset2_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 8: + if (FreeTempTileDataBuffersIfPossible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapLayout); + (*state)++; + } + break; + case 9: + DrawWholeMapView(); + (*state)++; + break; + case 10: + InitTilesetAnimations(); + sub_815A540(); + (*state)++; + break; + default: + if (map_post_load_hook_exec()) + return TRUE; + break; + } + return FALSE; +} + +void sub_8057430(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + gUnknown_2036E28 = 3; + ResetSafariZoneFlag_(); + LoadSaveblockMapHeader(); + LoadSaveblockObjEventScripts(); + UnfreezeObjectEvents(); + sub_8054E40(); + InitMapFromSavedGame(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + gUnknown_2031DE0 = TRUE; + if (UseContinueGameWarp() == TRUE) + { + ClearContinueGameWarpStatus(); + SetWarpDestinationToContinueGameWarp(); + WarpIntoMap(); + SetMainCallback2(CB2_LoadMap); + } + else + { + SetMainCallback1(CB1_Overworld); + CB2_ReturnToField(); + } +} + +void Overworld_CreditsMainCB(void) +{ + bool8 fading = !!gPaletteFade.active; + if (fading) + SetVBlankCallback(NULL); + RunTasks(); + AnimateSprites(); + sub_805ACF0(); + UpdateCameraPanning(); + BuildOamBuffer(); + UpdatePaletteFade(); + UpdateTilesetAnimations(); + DoScheduledBgTilemapCopiesToVram(); + if (fading) + SetFieldVBlankCallback(); +} + +bool8 sub_80574EC(void) +{ + if (gPaletteFade.active) + return TRUE; + else + return FALSE; +} + +bool32 Overworld_DoScrollSceneForCredits(u8 *state_p, const struct CreditsOverworldCmd * script, u8 a2) +{ + gUnknown_2031DE4 = script; + gUnknown_2036E28 = a2; + return sub_8057528(state_p, 0); +} + +bool32 sub_8057528(u8 *state, u8 unused) +{ + struct WarpData warp; + switch (*state) + { + case 0: + gUnknown_2031DEA = 0; + gUnknown_2031DE8 = 0; + (*state)++; + return FALSE; + case 1: + warp.mapGroup = gUnknown_2031DE4[gUnknown_2031DEA].unk_2; + warp.mapNum = gUnknown_2031DE4[gUnknown_2031DEA].unk_4; + warp.warpId = -1; + gUnknown_2031DEA++; + warp.x = gUnknown_2031DE4[gUnknown_2031DEA].unk_0; + warp.y = gUnknown_2031DE4[gUnknown_2031DEA].unk_2; + sWarpDestination = warp; + gUnknown_2031DE8 = gUnknown_2031DE4[gUnknown_2031DEA].unk_4; + WarpIntoMap(); + gPaletteFade.bufferTransferDisabled = TRUE; + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + gFieldCallback2 = sub_80574EC; + gMain.state = 0; + (*state)++; + return FALSE; + case 2: + if (sub_8057650()) + { + (*state)++; + return FALSE; + } + break; + case 3: + gFieldCamera.callback = sub_8057748; + SetFieldVBlankCallback(); + *state = 0; + return TRUE; + } + return FALSE; +} + +bool8 sub_8057650(void) +{ + u8 *state = &gMain.state; + switch (*state) + { + case 0: + InitOverworldBgs_NoResetHeap(); + mli0_load_map(FALSE); + (*state)++; + break; + case 1: + ScanlineEffect_Clear(); + ResetAllPicSprites(); + ResetCameraUpdateInfo(); + InstallCameraPanAheadCallback(); + FieldEffectActiveListClear(); + StartWeather(); + ResumePausedWeather(); + SetUpFieldTasks(); + RunOnResumeMapScript(); + (*state)++; + break; + case 2: + InitCurrentFlashLevelScanlineEffect(); + InitOverworldGraphicsRegisters(); + (*state)++; + break; + case 3: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 4: + copy_map_tileset1_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 5: + copy_map_tileset2_to_vram(gMapHeader.mapLayout); + (*state)++; + break; + case 6: + if (FreeTempTileDataBuffersIfPossible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapLayout); + (*state)++; + } + break; + case 7: + DrawWholeMapView(); + (*state)++; + break; + case 8: + InitTilesetAnimations(); + gPaletteFade.bufferTransferDisabled = FALSE; + FadeSelectedPals(FADE_FROM_BLACK, 0, 0x3FFFFFFF); + (*state)++; + break; + default: + return TRUE; + } + return FALSE; +} + +void sub_8057748(struct CameraObject * camera) +{ + if (gUnknown_2031DE8 == 0) + { + gUnknown_2031DEA++; + switch (gUnknown_2031DE4[gUnknown_2031DEA].unk_0) + { + case 0xFC: + case 0xFE: + return; + case 0xFF: + camera->movementSpeedX = 0; + camera->movementSpeedY = 0; + camera->callback = NULL; + CreateTask(sub_805781C, 0); + return; + case 0xFB: + camera->movementSpeedX = 0; + camera->movementSpeedY = 0; + camera->callback = NULL; + break; + case 0xFD: + camera->movementSpeedX = 0; + camera->movementSpeedY = 0; + camera->callback = NULL; + return; + default: + gUnknown_2031DE8 = gUnknown_2031DE4[gUnknown_2031DEA].unk_4; + camera->movementSpeedX = gUnknown_2031DE4[gUnknown_2031DEA].unk_0; + camera->movementSpeedY = gUnknown_2031DE4[gUnknown_2031DEA].unk_2; + break; + } + } + if (gUnknown_2031DE4[gUnknown_2031DEA].unk_0 == 0xFF) + { + camera->movementSpeedX = 0; + camera->movementSpeedY = 0; + } + else + gUnknown_2031DE8--; +} + +void sub_805781C(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); + gTasks[taskId].func = sub_8057854; +} + +void sub_8057854(u8 taskId) +{ + if (!gPaletteFade.active) + { + CleanupOverworldWindowsAndTilemaps(); + SetMainCallback2(CB2_LoadMap); + DestroyTask(taskId); + } +} |