pokeemerald/src/overworld.c

547 lines
14 KiB
C
Raw Normal View History

2017-09-30 19:08:28 +02:00
#include "global.h"
2018-02-12 15:01:43 +01:00
#include "overworld.h"
#include "battle_setup.h"
#include "berry.h"
// #include "cable_club.h"
#include "clock.h"
#include "event_data.h"
#include "field_camera.h"
// #include "field_control_avatar.h"
#include "field_effect.h"
#include "field_fadetransition.h"
#include "field_ground_effect.h"
#include "field_map_obj.h"
#include "field_map_obj_helpers.h"
#include "field_message_box.h"
#include "field_player_avatar.h"
#include "field_screen_effect.h"
// #include "field_special_scene.h"
#include "field_specials.h"
#include "field_tasks.h"
#include "field_weather.h"
#include "fieldmap.h"
// #include "fldeff_flash.h"
#include "heal_location.h"
#include "link.h"
#include "load_save.h"
#include "main.h"
#include "m4a.h"
#include "constants/maps.h"
#include "map_name_popup.h"
#include "menu.h"
#include "metatile_behavior.h"
#include "new_game.h"
#include "palette.h"
#include "play_time.h"
#include "random.h"
#include "roamer.h"
// #include "rotating_gate.h"
#include "safari_zone.h"
#include "script.h"
// #include "script_pokemon_80C4.h"
#include "secret_base.h"
#include "constants/songs.h"
#include "sound.h"
#include "constants/species.h"
#include "start_menu.h"
#include "task.h"
// #include "tileset_anim.h"
#include "time_events.h"
#include "tv.h"
#include "scanline_effect.h"
#include "wild_encounter.h"
#include "bg.h"
#include "money.h"
// event scripts
extern const u8 EventScript_WhiteOut[];
extern const u8 EventScript_271862[];
// vars
extern struct MapData * const gMapAttributes[];
extern struct MapHeader * const * const gMapGroups[];
extern s32 gMaxFlashLevel;
// functions
extern void HealPlayerParty(void);
extern void move_tilemap_camera_to_upper_left_corner(void);
extern void cur_mapheader_run_tileset_funcs_after_some_cpuset(void);
extern void DrawWholeMapView(void);
extern void copy_map_tileset1_tileset2_to_vram(struct MapData *);
extern void apply_map_tileset1_tileset2_palette(struct MapData *);
extern void ResetCyclingRoadChallengeData(void);
extern void ApplyNewEncryptionKeyToWord(u32 *word, u32 newKey);
2017-09-30 19:08:28 +02:00
2018-02-12 15:01:43 +01:00
// this file's functions
static void Overworld_ResetStateAfterWhiteOut(void);
void ChooseAmbientCrySpecies(void);
2017-09-30 19:08:28 +02:00
2018-02-12 15:01:43 +01:00
// IWRAM bss vars
2017-09-30 19:08:28 +02:00
IWRAM_DATA void *gUnknown_03000E0C;
IWRAM_DATA u8 gUnknown_03000E10[4];
IWRAM_DATA u8 (*gUnknown_03000E14)(u32);
IWRAM_DATA u8 gUnknown_03000E18;
IWRAM_DATA u8 gUnknown_03000E19;
IWRAM_DATA void *rom4_c_unused_03000e1c;
2018-02-12 15:01:43 +01:00
// EWRAM vars
EWRAM_DATA struct WarpData gUnknown_020322DC = {0};
EWRAM_DATA struct WarpData gWarpDestination = {0}; // new warp position
EWRAM_DATA struct WarpData gUnknown_020322EC = {0};
EWRAM_DATA struct WarpData gUnknown_020322F4 = {0};
EWRAM_DATA u16 gLastMapSectionId = 0;
// EWRAM_DATA struct UnkPlayerStruct gUnknown_02029810 = {0};
// EWRAM_DATA u16 sAmbientCrySpecies = 0;
// EWRAM_DATA bool8 sIsAmbientCryWaterMon = FALSE;
// EWRAM_DATA struct LinkPlayerMapObject gLinkPlayerMapObjects[4] = {0};
// const rom data
const struct WarpData sDummyWarpData =
{
.mapGroup = -1,
.mapNum = -1,
.warpId = -1,
.x = -1,
.y = -1,
};
const u8 sUnusedData[] =
{
0xB0, 0x04, 0x00, 0x00,
0x10, 0x0E, 0x00, 0x00,
0xB0, 0x04, 0x00, 0x00,
0x60, 0x09, 0x00, 0x00,
0x32, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00,
0xD4, 0xFF, 0xFF, 0xFF,
0x2C, 0x00, 0x00, 0x00,
};
const struct UCoords32 gUnknown_08339D64[] =
{
{ 0, 0},
{ 0, 1},
{ 0, -1},
{-1, 0},
{ 1, 0},
{-1, 1},
{ 1, 1},
{-1, -1},
{ 1, -1},
};
const struct BgTemplate gUnknown_08339DAC[] =
{
{
.bg = 0,
.charBaseIndex = 2,
.mapBaseIndex = 31,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0
},
{
.bg = 1,
.charBaseIndex = 0,
.mapBaseIndex = 29,
.screenSize = 0,
.paletteMode = 0,
.priority = 1,
.baseTile = 0
},
{
.bg = 2,
.charBaseIndex = 0,
.mapBaseIndex = 28,
.screenSize = 0,
.paletteMode = 0,
.priority = 2,
.baseTile = 0
},
{
.bg = 3,
.charBaseIndex = 0,
.mapBaseIndex = 30,
.screenSize = 0,
.paletteMode = 0,
.priority = 3,
.baseTile = 0
}
};
const struct ScanlineEffectParams gUnknown_08339DBC =
{
(void *)REG_ADDR_WIN0H,
((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1,
1,
0,
};
u8 sub_80879D8(struct LinkPlayerMapObject *, struct MapObject *, u8);
u8 sub_80879F8(struct LinkPlayerMapObject *, struct MapObject *, u8);
u8 sub_80879FC(struct LinkPlayerMapObject *, struct MapObject *, u8);
u8 (*const gUnknown_08339DC8[])(struct LinkPlayerMapObject *, struct MapObject *, u8) =
{
sub_80879D8,
sub_80879F8,
sub_80879FC,
};
u8 sub_8087A1C(struct LinkPlayerMapObject *, struct MapObject *, u8);
u8 sub_8087A20(struct LinkPlayerMapObject *, struct MapObject *, u8);
u8 sub_8087A88(struct LinkPlayerMapObject *, struct MapObject *, u8);
u8 (*const gUnknown_08339DD4[])(struct LinkPlayerMapObject *, struct MapObject *, u8) =
{
sub_8087A1C,
sub_8087A20,
sub_8087A20,
sub_8087A20,
sub_8087A20,
sub_8087A1C,
sub_8087A1C,
sub_8087A88,
sub_8087A88,
sub_8087A88,
sub_8087A88,
};
void sub_8087AA0(struct LinkPlayerMapObject *, struct MapObject *);
void sub_8087AA8(struct LinkPlayerMapObject *, struct MapObject *);
void (*const gUnknown_08339E00[])(struct LinkPlayerMapObject *, struct MapObject *) =
{
sub_8087AA0,
sub_8087AA8,
};
// code
void DoWhiteOut(void)
{
ScriptContext2_RunNewScript(EventScript_WhiteOut);
SetMoney(&gSaveBlock1Ptr->money, GetMoney(&gSaveBlock1Ptr->money) / 2);
HealPlayerParty();
Overworld_ResetStateAfterWhiteOut();
Overworld_SetWarpDestToLastHealLoc();
warp_in();
}
void Overworld_ResetStateAfterFly(void)
{
player_avatar_init_params_reset();
FlagClear(FLAG_SYS_CYCLING_ROAD);
FlagClear(FLAG_SYS_CRUISE_MODE);
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
}
void Overworld_ResetStateAfterTeleport(void)
{
player_avatar_init_params_reset();
FlagClear(FLAG_SYS_CYCLING_ROAD);
FlagClear(FLAG_SYS_CRUISE_MODE);
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
ScriptContext2_RunNewScript(EventScript_271862);
}
void Overworld_ResetStateAfterDigEscRope(void)
{
player_avatar_init_params_reset();
FlagClear(FLAG_SYS_CYCLING_ROAD);
FlagClear(FLAG_SYS_CRUISE_MODE);
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
}
static void Overworld_ResetStateAfterWhiteOut(void)
{
player_avatar_init_params_reset();
FlagClear(FLAG_SYS_CYCLING_ROAD);
FlagClear(FLAG_SYS_CRUISE_MODE);
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
if (VarGet(VAR_0x4039) == 1)
{
VarSet(VAR_0x4039, 0);
VarSet(VAR_0x4037, 0);
}
}
void sub_8084788(void)
{
FlagClear(FLAG_SYS_SAFARI_MODE);
ChooseAmbientCrySpecies();
ResetCyclingRoadChallengeData();
UpdateLocationHistoryForRoamer();
RoamerMoveToOtherLocationSet();
}
void ResetGameStats(void)
{
s32 i;
for (i = 0; i < NUM_GAME_STATS; i++)
SetGameStat(i, 0);
}
void IncrementGameStat(u8 index)
{
if (index < NUM_USED_GAME_STATS)
{
u32 statVal = GetGameStat(index);
if (statVal < 0xFFFFFF)
statVal++;
else
statVal = 0xFFFFFF;
SetGameStat(index, statVal);
}
}
u32 GetGameStat(u8 index)
{
if (index >= NUM_USED_GAME_STATS)
return 0;
return gSaveBlock1Ptr->gameStats[index] ^ gSaveBlock2Ptr->encryptionKey;
}
void SetGameStat(u8 index, u32 value)
{
if (index < NUM_USED_GAME_STATS)
gSaveBlock1Ptr->gameStats[index] = value ^ gSaveBlock2Ptr->encryptionKey;
}
void ApplyNewEncryptionKeyToGameStats(u32 newKey)
{
u8 i;
for (i = 0; i < NUM_GAME_STATS; i++)
ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->gameStats[i], newKey);
}
void LoadMapObjTemplatesFromHeader(void)
{
// Clear map object templates
CpuFill32(0, gSaveBlock1Ptr->mapObjectTemplates, sizeof(gSaveBlock1Ptr->mapObjectTemplates));
// Copy map header events to save block
CpuCopy32(gMapHeader.events->mapObjects,
gSaveBlock1Ptr->mapObjectTemplates,
gMapHeader.events->mapObjectCount * sizeof(struct MapObjectTemplate));
}
void LoadSaveblockMapObjScripts(void)
{
struct MapObjectTemplate *mapHeaderObjTemplates = gMapHeader.events->mapObjects;
struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates;
s32 i;
for (i = 0; i < 64; i++)
savObjTemplates[i].script = mapHeaderObjTemplates[i].script;
}
void Overworld_SetMapObjTemplateCoords(u8 localId, s16 x, s16 y)
{
s32 i;
struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates;
for (i = 0; i < 64; i++)
{
struct MapObjectTemplate *mapObjectTemplate = &savObjTemplates[i];
if (mapObjectTemplate->localId == localId)
{
mapObjectTemplate->x = x;
mapObjectTemplate->y = y;
return;
}
}
}
void Overworld_SetMapObjTemplateMovementType(u8 localId, u8 movementType)
{
s32 i;
struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates;
for (i = 0; i < 64; i++)
{
struct MapObjectTemplate *mapObjectTemplate = &savObjTemplates[i];
if (mapObjectTemplate->localId == localId)
{
mapObjectTemplate->movementType = movementType;
return;
}
}
}
void mapdata_load_assets_to_gpu_and_full_redraw(void)
{
move_tilemap_camera_to_upper_left_corner();
copy_map_tileset1_tileset2_to_vram(gMapHeader.mapData);
apply_map_tileset1_tileset2_palette(gMapHeader.mapData);
DrawWholeMapView();
cur_mapheader_run_tileset_funcs_after_some_cpuset();
}
struct MapData *get_mapdata_header(void)
{
u16 mapDataId = gSaveBlock1Ptr->mapDataId;
if (mapDataId)
return gMapAttributes[mapDataId - 1];
return NULL;
}
void ApplyCurrentWarp(void)
{
gUnknown_020322DC = gSaveBlock1Ptr->location;
gSaveBlock1Ptr->location = gWarpDestination;
gUnknown_020322EC = sDummyWarpData;
gUnknown_020322F4 = sDummyWarpData;
}
void set_warp2_warp3_to_neg_1(void)
{
gUnknown_020322EC = sDummyWarpData;
gUnknown_020322F4 = sDummyWarpData;
}
void SetWarpData(struct WarpData *warp, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y)
{
warp->mapGroup = mapGroup;
warp->mapNum = mapNum;
warp->warpId = warpId;
warp->x = x;
warp->y = y;
}
bool32 warp_data_is_not_neg_1(struct WarpData *warp)
{
if (warp->mapGroup != -1)
return FALSE;
if (warp->mapNum != -1)
return FALSE;
if (warp->warpId != -1)
return FALSE;
if (warp->x != -1)
return FALSE;
if (warp->y != -1)
return FALSE;
return TRUE;
}
struct MapHeader *const Overworld_GetMapHeaderByGroupAndId(u16 mapGroup, u16 mapNum)
{
return gMapGroups[mapGroup][mapNum];
}
struct MapHeader *const warp1_get_mapheader(void)
{
return Overworld_GetMapHeaderByGroupAndId(gWarpDestination.mapGroup, gWarpDestination.mapNum);
}
void set_current_map_header_from_sav1_save_old_name(void)
{
gLastMapSectionId = gMapHeader.regionMapSectionId;
gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum);
gSaveBlock1Ptr->mapDataId = gMapHeader.mapDataId;
gMapHeader.mapData = get_mapdata_header();
}
void LoadSaveblockMapHeader(void)
{
gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum);
gMapHeader.mapData = get_mapdata_header();
}
void update_camera_pos_from_warpid(void)
{
if (gSaveBlock1Ptr->location.warpId >= 0 && gSaveBlock1Ptr->location.warpId < gMapHeader.events->warpCount)
{
gSaveBlock1Ptr->pos.x = gMapHeader.events->warps[gSaveBlock1Ptr->location.warpId].x;
gSaveBlock1Ptr->pos.y = gMapHeader.events->warps[gSaveBlock1Ptr->location.warpId].y;
}
else if (gSaveBlock1Ptr->location.x >= 0 && gSaveBlock1Ptr->location.y >= 0)
{
gSaveBlock1Ptr->pos.x = gSaveBlock1Ptr->location.x;
gSaveBlock1Ptr->pos.y = gSaveBlock1Ptr->location.y;
}
else
{
gSaveBlock1Ptr->pos.x = gMapHeader.mapData->width / 2;
gSaveBlock1Ptr->pos.y = gMapHeader.mapData->height / 2;
}
}
void warp_in(void)
{
ApplyCurrentWarp();
set_current_map_header_from_sav1_save_old_name();
update_camera_pos_from_warpid();
}
void Overworld_SetWarpDestination(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y)
{
SetWarpData(&gWarpDestination, mapGroup, mapNum, warpId, x, y);
}
void warp1_set_2(s8 mapGroup, s8 mapNum, s8 warpId)
{
Overworld_SetWarpDestination(mapGroup, mapNum, warpId, -1, -1);
}
void saved_warp2_set(int unused, s8 mapGroup, s8 mapNum, s8 warpId)
{
SetWarpData(&gSaveBlock1Ptr->warp2, mapGroup, mapNum, warpId, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y);
}
void saved_warp2_set_2(int unused, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y)
{
SetWarpData(&gSaveBlock1Ptr->warp2, mapGroup, mapNum, warpId, x, y);
}
void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused)
{
gWarpDestination = gSaveBlock1Ptr->warp2;
}
void sub_8084CCC(u8 a1)
{
const struct HealLocation *warp = GetHealLocationPointer(a1);
if (warp)
Overworld_SetWarpDestination(warp->group, warp->map, -1, warp->x, warp->y);
}
void Overworld_SetWarpDestToLastHealLoc(void)
{
gWarpDestination = gSaveBlock1Ptr->lastHealLocation;
}
void Overworld_SetHealLocationWarp(u8 healLocationId)
{
const struct HealLocation *healLocation = GetHealLocationPointer(healLocationId);
if (healLocation != NULL)
SetWarpData(&gSaveBlock1Ptr->lastHealLocation, healLocation->group, healLocation->map, -1, healLocation->x, healLocation->y);
}
2017-09-30 19:08:28 +02:00
2018-02-12 15:01:43 +01:00
void sub_8084D5C(s16 a1, s16 a2)
{
u8 currMapType = Overworld_GetMapTypeOfSaveblockLocation();
u8 destMapType = GetMapTypeByGroupAndId(gWarpDestination.mapGroup, gWarpDestination.mapNum);
if (is_light_level_1_2_3_5_or_6(currMapType) && is_light_level_1_2_3_5_or_6(destMapType) != TRUE)
sub_8084DD4(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, a1 - 7, a2 - 6);
}
2017-09-30 19:08:28 +02:00
2018-02-12 15:01:43 +01:00
void sub_8084DD4(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y)
{
SetWarpData(&gSaveBlock1Ptr->warp4, mapGroup, mapNum, warpId, x, y);
}