tmc/src/game.c

409 lines
9.8 KiB
C

/**
* @file game.c
* @ingroup Tasks
*
* @brief Game task
*/
#include "game.h"
#include "area.h"
#include "asm.h"
#include "backgroundAnimations.h"
#include "common.h"
#include "droptables.h"
#include "enemy.h"
#include "entity.h"
#include "fileselect.h"
#include "flags.h"
#include "functions.h"
#include "item.h"
#include "itemMetaData.h"
#include "itemMetaData.h"
#include "kinstone.h"
#include "main.h"
#include "manager/diggingCaveEntranceManager.h"
#include "menu.h"
#include "message.h"
#include "npc.h"
#include "object.h"
#include "player.h"
#include "player.h"
#include "room.h"
#include "roomid.h"
#include "save.h"
#include "screen.h"
#include "sound.h"
#include "subtask.h"
#include "transitions.h"
#include "ui.h"
// Game task
typedef void(GameState)(void);
typedef void(GameMainState)(void);
static GameState GameTask_Transition;
static GameState GameTask_Init;
static GameState GameTask_Exit;
static GameState GameTask_Main;
static GameMainState GameMain_InitRoom;
static GameMainState GameMain_ChangeRoom;
static GameMainState GameMain_Update;
static GameMainState GameMain_ChangeArea;
GameMainState GameMain_MinishPortal;
static GameMainState GameMain_BarrelUpdate;
/*static GameMainState 00000000;*/
GameMainState GameMain_Subtask;
extern u8 gUpdateVisibleTiles;
extern void FinalizeSave(void);
extern void ClearArmosData(void);
extern void ClearRoomMemory(void);
extern void ClearMenuSavestate(void);
extern void ResetUI(void);
extern void sub_0806FD8C(void);
extern void sub_080300C4(void);
extern u32 sub_0805BC04(void);
extern void DeleteSleepingEntities(void);
extern bool32 UpdateLightLevel(void);
extern void sub_080185F8(void);
extern void UpdateDoorTransition(void);
extern bool32 CheckInitPortal(void);
extern void UpdateCarriedObject(void);
extern void CollisionMain(void);
extern void sub_0805BB74(s32);
extern void CreateZeldaFollower(void);
extern void LoadRoomGfx(void);
extern void RecycleEntities(void);
extern void sub_0804AF90(void);
extern void CallRoomProp6(void);
static void UpdateWindcrests(void);
static void InitializeEntities(void);
static void sub_08051D98(void);
static void sub_08051DCC(void);
void sub_08054974(u32 worldEventId, bool32 param_2);
void GameTask(void) {
static GameState* const sStates[] = {
GameTask_Transition,
GameTask_Init,
GameTask_Main,
GameTask_Exit,
};
gRoomTransition.frameCount++;
sStates[gMain.state]();
#ifdef DEMO_USA
if (gSave.demo_timer != 0) {
if (--gSave.demo_timer == 0) {
SetFade(FADE_IN_OUT | FADE_BLACK_WHITE | FADE_INSTANT, 2);
gMain.state = GAMETASK_EXIT;
}
}
#endif
}
static void GameTask_Transition(void) {
// wait for file select to fade out
if (gFadeControl.active)
return;
DispReset(1);
InitSoundPlayingInfo();
zMallocInit();
ResetUI();
ClearMenuSavestate();
MemClear(&gRoomTransition, sizeof(gRoomTransition));
ClearRoomMemory();
ClearArmosData();
FinalizeSave();
// spawn in with saved status
MemCopy(&gSave.saved_status, &gRoomTransition.player_status, sizeof(gRoomTransition.player_status));
gRoomTransition.type = TRANSITION_FADE_BLACK_SLOW;
ResetTmpFlags();
gMain.state = GAMETASK_INIT;
gMain.substate = GAMEMAIN_INITROOM;
}
static void GameTask_Init(void) {
DispReset(1);
gFadeControl.mask = 0xffffffff;
MemClear(&gOAMControls, 0xB74);
MemClear(&gUI, sizeof(gUI));
EraseAllEntities();
SetBGDefaults();
ClearTileMaps();
ResetPalettes();
ResetPaletteTable(1);
sub_0806FD8C();
gRoomControls.area = gRoomTransition.player_status.area_next;
gRoomControls.room = gRoomTransition.player_status.room_next;
LoadGfxGroups();
gGFXSlots.unk0 = 1;
gMain.state = GAMETASK_MAIN;
}
static void GameTask_Main(void) {
static GameMainState* const sStates[] = {
GameMain_InitRoom,
GameMain_ChangeRoom,
GameMain_Update,
GameMain_ChangeArea,
GameMain_MinishPortal,
GameMain_BarrelUpdate,
0,
GameMain_Subtask,
};
sStates[gMain.substate]();
}
static void GameMain_InitRoom(void) {
SetInitializationPriority();
gScreen.lcd.displayControl = DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP;
gMain.substate = GAMEMAIN_CHANGEROOM;
gRoomTransition.transitioningOut = 0;
gRoomTransition.field_0x4[0] = 0;
gRoomTransition.field_0x4[1] = 0;
MessageInitialize();
InitRoom();
InitUI(FALSE);
InitializeEntities();
#ifndef EU
sub_0801855C();
#endif
}
static void GameMain_ChangeRoom(void) {
UpdateEntities();
if (!UpdateLightLevel())
UpdateScroll();
UpdateBgAnimations();
UpdateScrollVram();
DrawUI();
UpdateManagers();
FlushSprites();
DrawUIElements();
UpdateCarriedObject();
DrawEntities();
CopyOAM();
if (gFadeControl.active || gRoomControls.reload_flags != 0)
return;
UpdateFakeScroll();
if (gArea.bgm != gArea.queued_bgm) {
gArea.bgm = gArea.queued_bgm;
SoundReq(gArea.queued_bgm | SONG_PLAY_VOL_RESET);
}
DeleteSleepingEntities();
if (sub_0805BC04())
return;
UpdatePlayerMapCoords();
ClearEventPriority();
UpdateWindcrests();
sub_080300C4();
gMain.substate = GAMEMAIN_UPDATE;
SetPlayerControl(0);
gPauseMenuOptions.disabled = 0;
#if defined(USA) || defined(DEMO_USA)
if (gArea.unk28.textBaseIndex != 0xff) {
sub_0801855C();
}
CreateMiscManager();
CheckAreaDiscovery();
#elif defined(EU)
CheckAreaDiscovery();
sub_0801855C();
#elif defined(JP)
CheckAreaDiscovery();
if (gArea.unk28.textBaseIndex != 0xff) {
sub_0801855C();
}
#elif defined(DEMO_JP)
if (gRoomTransition.field31)
CheckAreaDiscovery();
if (gArea.unk28.textBaseIndex != 0xff) {
sub_0801855C();
}
CreateMiscManager();
#endif
if (!gRoomVars.didEnterScrolling) {
RequestPriorityDuration(NULL, 1);
}
}
static void GameMain_Update(void) {
if (CheckInitPauseMenu() || CheckInitPortal()) {
return;
}
UpdateTimerCallbacks();
// leave early if player is now entering a portal
if (gMain.substate != GAMEMAIN_UPDATE) {
return;
}
if ((gMessage.state & MESSAGE_ACTIVE) || gPriorityHandler.priority_timer != 0)
PausePlayer();
FlushSprites();
UpdateEntities();
UpdateDoorTransition();
CollisionMain();
UpdateScroll();
UpdateBgAnimations();
UpdateScrollVram();
DecreasePortalTimer();
DrawUI();
UpdateManagers();
DrawUIElements();
UpdateCarriedObject();
DrawEntities();
CheckRoomExit();
UpdatePlayerMapCoords();
CheckGameOver();
sub_080185F8();
CopyOAM();
switch (gRoomControls.reload_flags) {
case RELOAD_ALL:
gPlayerState.queued_action = PLAYER_ROOMTRANSITION;
gMain.substate = GAMEMAIN_CHANGEROOM;
SetRoomReloadPriority();
sub_08051D98();
break;
case RELOAD_ENTITIES:
gPlayerState.queued_action = PLAYER_ROOMTRANSITION;
gMain.substate = GAMEMAIN_CHANGEROOM;
SetRoomReloadPriority();
sub_08051DCC();
break;
}
}
static void GameMain_BarrelUpdate(void) {
if (CheckInitPauseMenu())
return;
UpdateEntities();
CollisionMain();
DrawUI();
UpdateManagers();
FlushSprites();
DrawUIElements();
UpdateCarriedObject();
DrawEntities();
CheckRoomExit();
CheckGameOver();
CopyOAM();
if (!gFadeControl.active)
ClearEventPriority();
}
static void GameMain_ChangeArea(void) {
FlushSprites();
DrawUIElements();
DrawEntities();
gMain.pad = 1;
CopyOAM();
if (!gFadeControl.active) {
DispReset(1);
gMain.state = GAMETASK_INIT;
gMain.substate = GAMEMAIN_INITROOM;
gRoomTransition.transitioningOut = 1;
}
}
static void GameTask_Exit(void) {
#ifdef DEMO_USA
if (!gFadeControl.active)
DoSoftReset();
#else
SetFade(FADE_IN_OUT | FADE_BLACK_WHITE | FADE_INSTANT, 8);
SetTask(TASK_GAMEOVER);
#endif
}
// TODO End of GameTask?
static void InitializeEntities(void) {
sub_08052EA0();
sub_0804AF90();
CallRoomProp6();
InitializePlayer();
gDiggingCaveEntranceTransition.entrance = NULL;
InitializeCamera();
gUpdateVisibleTiles = 1;
LoadRoomBgm();
SetColor(0, 0);
LoadRoom();
CreateZeldaFollower();
CallRoomProp5And7();
sub_0805329C();
UpdateScrollVram();
sub_0805BB74(-1);
UpdatePlayerRoomStatus();
}
static void sub_08051D98(void) {
sub_08052EA0();
gRoomVars.didEnterScrolling = TRUE;
// remove old entities, unless persistent
RecycleEntities();
sub_0804AF90();
CallRoomProp6();
LoadRoomGfx();
LoadRoomBgm();
LoadRoom();
CallRoomProp5And7();
SetPlayerControl(1);
}
static void sub_08051DCC(void) {
gRoomControls.area = gRoomTransition.player_status.area_next;
gRoomControls.room = gRoomTransition.player_status.room_next;
RoomExitCallback();
gRoomTransition.type = TRANSITION_3;
InitRoom();
sub_08052EA0();
RecycleEntities();
sub_0804AF90();
CallRoomProp6();
LoadRoomBgm();
}
static void UpdateWindcrests(void) {
if (AreaIsOverworld()) {
const OverworldLocation* location;
u32 hi_x, hi_y;
s32 x, y;
x = gPlayerEntity.base.x.HALF.HI;
if (x < 0)
x += 0xf;
hi_x = x >> 4;
y = gPlayerEntity.base.y.HALF.HI;
if (y < 0)
y += 0xf;
hi_y = y >> 4;
for (location = gOverworldLocations; location->minX != 0xFF; location++) {
if (location->minX <= hi_x && location->maxX >= hi_x && location->minY <= hi_y && location->maxY >= hi_y) {
gSave.windcrests |= 1 << location->windcrestId;
break;
}
}
}
}