mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-15 04:45:32 -05:00
1658 lines
44 KiB
C
1658 lines
44 KiB
C
#include "global.h"
|
|
#include "gflib.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_fadetransition.h"
|
|
#include "field_message_box.h"
|
|
#include "field_player_avatar.h"
|
|
#include "field_screen_effect.h"
|
|
#include "field_specials.h"
|
|
#include "field_weather.h"
|
|
#include "fieldmap.h"
|
|
#include "heal_location.h"
|
|
#include "link.h"
|
|
#include "load_save.h"
|
|
#include "m4a.h"
|
|
#include "map_name_popup.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 "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 "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);
|
|
void MoveSaveBlocks_ResetHeap_(void);
|
|
void sub_8056E80(void);
|
|
void CB1_UpdateLinkState(void);
|
|
void ResetAllMultiplayerState(void);
|
|
void do_load_map_stuff_loop(u8 *state);
|
|
bool32 sub_8056CD8(u8 *state);
|
|
bool32 map_loading_iteration_3(u8 *state);
|
|
bool32 map_loading_iteration_2_link(u8 *state);
|
|
|
|
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();
|
|
mapheader_run_script_with_tag_x5();
|
|
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
|
|
});
|
|
}
|
|
}
|