Files
tmc/src/manager/holeManager.c
T
2025-03-09 18:58:00 +00:00

323 lines
15 KiB
C

/**
* @file holeManager.c
* @ingroup Managers
*
* @brief Hole that you can fall into.
*/
#include "manager/holeManager.h"
#include "common.h"
#include "flags.h"
#include "object.h"
#include "room.h"
#include "screen.h"
#include "game.h"
#include "manager/lightManager.h"
#include "assets/gfx_offsets.h"
#include "functions.h"
typedef enum {
HOLE_TRANSITION_ABSOLUTE,
HOLE_TRANSITION_RELATIVE,
HOLE_TRANSITION_ABSOLUTE_MINISH,
} HoleTransitionType;
typedef struct {
u32 gfx;
u16 offset_x;
u16 offset_y;
u16 x;
u16 y;
} HoleTransitionParallaxBackground;
typedef struct {
u8 type;
u8 subtype;
u8 unk_2;
u8 unk_3;
u16 x;
u16 y;
} HoleTransitionParallaxEntity;
typedef struct HoleTransition {
u8 type;
u8 area;
u8 room;
u8 layer;
u16 x;
u16 y;
u8 hole_x;
u8 hole_y;
u8 hole_width;
u8 hole_height;
const HoleTransitionParallaxBackground* parallax_background;
const HoleTransitionParallaxEntity* parallax_entity;
} HoleTransition;
void HoleManager_Init(HoleManager*);
void HoleManager_Update(HoleManager*);
void (*const HoleManager_Actions[])(HoleManager*) = {
HoleManager_Init,
HoleManager_Update,
};
const HoleTransitionParallaxBackground gHoleTransitionParallaxBackgrounds[] = {
{ offset_gfx_unknown_6, 0x00c4, 0x0030, 0x0310, 0x13c8 },
{ offset_gfx_unknown_6 + 0x800, 0x00c4, 0x0030, 0x0310, 0x13c8 },
{ offset_gfx_unknown_6 + 0x800 * 2, 0xfffa, 0x00de, 0x05d0, 0x0410 },
{ offset_gfx_unknown_6 + 0x800 * 3, 0x0024, 0x0004, 0x0290, 0x04e0 },
{ offset_gfx_unknown_6 + 0x800 * 4, 0x0058, 0x0014, 0x0280, 0x0cf0 },
{ offset_gfx_unknown_6 + 0x800 * 5, 0x002c, 0x0004, 0x04a0, 0x0cf0 },
{ offset_gfx_unknown_7, 0x0060, 0x0010, 0x0170, 0x08e0 },
{ offset_gfx_unknown_7 + 0x800, 0x001c, 0x00d0, 0x05b0, 0x0e20 },
{ offset_gfx_unknown_7 + 0x800 * 2, 0x005c, 0x00a4, 0x0290, 0x1b48 },
};
const HoleTransitionParallaxEntity gHoleTransitionParallaxEntities[] = {
{ 0x00, 0x00, 0x00, 0x00, 0x0088, 0x0068 }, { 0x01, 0x01, 0x00, 0x00, 0x0088, 0x0068 },
{ 0x02, 0x02, 0x00, 0x00, 0x00b8, 0x0068 }, { 0x04, 0x04, 0x00, 0x00, 0x00b8, 0x0068 },
{ 0x05, 0x00, 0x00, 0x00, 0x0078, 0x00b8 }, { 0x06, 0x01, 0x00, 0x00, 0x0048, 0x0040 },
{ 0x07, 0x02, 0x00, 0x00, 0x0090, 0x0040 }, { 0x07, 0x03, 0x00, 0x00, 0x0240, 0x0050 },
{ 0x07, 0x04, 0x00, 0x00, 0x0158, 0x0100 }, { 0x08, 0x05, 0x00, 0x00, 0x007c, 0x0050 },
{ 0x09, 0x06, 0x00, 0x00, 0x0078, 0x0070 }, { 0x0a, 0x07, 0x00, 0x00, 0x0060, 0x0058 },
{ 0x0b, 0x08, 0x00, 0x00, 0x0081, 0x005e }, { 0x0c, 0x09, 0x00, 0x00, 0x0080, 0x0058 },
{ 0x0d, 0x0a, 0x00, 0x00, 0x0060, 0x0038 }, { 0x0e, 0x0b, 0x00, 0x00, 0x0260, 0x0064 },
{ 0x0f, 0x00, 0x00, 0x00, 0x00a8, 0x0148 },
};
const HoleTransition gHoleTransitions[] = {
{ 0x00, 0x48, 0x14, 0x02, 0x00e8, 0x00c8, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x00, 0x51, 0x00, 0x02, 0x00c0, 0x00f8, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[0], NULL },
{ 0x01, 0x58, 0x1b, 0x02, 0xfeb0, 0x0000, 0x1d, 0x06, 0x05, 0x02, &gHoleTransitionParallaxBackgrounds[2], NULL },
{ 0x01, 0x58, 0x1d, 0x01, 0xffe0, 0xff20, 0x09, 0x13, 0x03, 0x03, NULL, &gHoleTransitionParallaxEntities[16] },
{ 0x01, 0x58, 0x1c, 0x01, 0xfff0, 0x0000, 0x08, 0x05, 0x03, 0x03, &gHoleTransitionParallaxBackgrounds[3], NULL },
{ 0x01, 0x58, 0x20, 0x01, 0xfff0, 0x0000, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[4], NULL },
{ 0x01, 0x58, 0x22, 0x01, 0xffe0, 0x0000, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[5], NULL },
{ 0x00, 0x62, 0x11, 0x01, 0x00c8, 0x0038, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x01, 0x60, 0x20, 0x01, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[0] },
{ 0x01, 0x60, 0x21, 0x01, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[1] },
{ 0x01, 0x60, 0x2e, 0x01, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[2] },
{ 0x01, 0x60, 0x11, 0x01, 0xffc0, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[3] },
{ 0x00, 0x60, 0x31, 0x01, 0x0078, 0x00a8, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x00, 0x51, 0x00, 0x02, 0x00c0, 0x00f8, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[1], NULL },
{ 0x01, 0x08, 0x01, 0x01, 0x0000, 0x0000, 0x1d, 0x1d, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x1d, 0x1d, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x23, 0x03, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x32, 0x03, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x03, 0x13, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x37, 0x10, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x2f, 0x18, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x16, 0x2b, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x25, 0x2c, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x32, 0x2d, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x0d, 0x35, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x17, 0x37, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x1d, 0x38, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x36, 0x38, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x38, 0x19, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x3a, 0x2e, 0x01, 0x01, NULL, NULL },
{ 0x01, 0x08, 0x02, 0x01, 0x0000, 0x0000, 0x30, 0x39, 0x01, 0x01, NULL, NULL },
{ 0x00, 0x1a, 0x00, 0x01, 0x0058, 0x0048, 0x18, 0x1b, 0x03, 0x03, NULL, NULL },
{ 0x01, 0x70, 0x0f, 0x01, 0x01e0, 0x0070, 0x08, 0x03, 0x04, 0x04, NULL, NULL },
{ 0x01, 0x70, 0x10, 0x01, 0x0000, 0x0090, 0x14, 0x05, 0x05, 0x03, NULL, NULL },
{ 0x01, 0x70, 0x10, 0x01, 0x0000, 0x0090, 0x21, 0x05, 0x04, 0x03, NULL, NULL },
{ 0x00, 0x70, 0x0c, 0x01, 0x0078, 0x00a0, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[4] },
{ 0x01, 0x70, 0x15, 0x01, 0x01e0, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[5] },
{ 0x01, 0x70, 0x19, 0x01, 0x00f0, 0x0000, 0x05, 0x08, 0x04, 0x04, NULL, NULL },
{ 0x01, 0x70, 0x1b, 0x01, 0x0000, 0x0000, 0x08, 0x02, 0x02, 0x04, NULL, &gHoleTransitionParallaxEntities[6] },
{ 0x01, 0x70, 0x1d, 0x01, 0xfe30, 0x0000, 0x23, 0x02, 0x02, 0x04, NULL, &gHoleTransitionParallaxEntities[7] },
{ 0x01, 0x70, 0x1f, 0x01, 0xff10, 0xff60, 0x13, 0x0e, 0x07, 0x04, NULL, &gHoleTransitionParallaxEntities[8] },
{ 0x01, 0x70, 0x21, 0x01, 0x0000, 0x0090, 0x06, 0x03, 0x04, 0x04, NULL, NULL },
{ 0x01, 0x70, 0x26, 0x01, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[9] },
{ 0x01, 0x70, 0x29, 0x01, 0x0000, 0x0000, 0x06, 0x06, 0x03, 0x02, NULL, &gHoleTransitionParallaxEntities[10] },
{ 0x01, 0x70, 0x2c, 0x01, 0x0000, 0x0000, 0x12, 0x0c, 0x04, 0x04, NULL, NULL },
{ 0x01, 0x70, 0x32, 0x01, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[11] },
{ 0x01, 0x70, 0x32, 0x02, 0x00f0, 0x0000, 0x07, 0x04, 0x02, 0x02, NULL, NULL },
{ 0x01, 0x70, 0x32, 0x01, 0x00f0, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[12] },
{ 0x01, 0x70, 0x32, 0x01, 0x01e0, 0x0000, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[13] },
{ 0x01, 0x70, 0x32, 0x01, 0x0000, 0x00a0, 0x00, 0x00, 0x00, 0x00, NULL, &gHoleTransitionParallaxEntities[14] },
{ 0x00, 0x31, 0x00, 0x01, 0x0078, 0x0068, 0x25, 0x04, 0x03, 0x03, NULL, &gHoleTransitionParallaxEntities[15] },
{ 0x00, 0x70, 0x00, 0x02, 0x01d8, 0x00d8, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x01, 0x88, 0x1e, 0x01, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[6], NULL },
{ 0x01, 0x88, 0x2c, 0x01, 0x0000, 0xff30, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[7], NULL },
{ 0x01, 0x88, 0x3a, 0x01, 0x0000, 0xffe0, 0x00, 0x00, 0x00, 0x00, &gHoleTransitionParallaxBackgrounds[8], NULL },
{ 0x00, 0x88, 0x06, 0x01, 0x00a8, 0x0088, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x02, 0x23, 0x01, 0x01, 0x0078, 0x0078, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x02, 0x23, 0x00, 0x01, 0x00a8, 0x0060, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x02, 0x22, 0x04, 0x01, 0x00a8, 0x0058, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x02, 0x23, 0x03, 0x01, 0x0078, 0x0078, 0x00, 0x00, 0x00, 0x00, NULL, NULL },
{ 0x00, 0x41, 0x01, 0x01, 0x0078, 0x0050, 0x2f, 0x27, 0x03, 0x03, NULL, NULL },
};
void HoleManager_Main(HoleManager* this) {
HoleManager_Actions[super->action](this);
}
bool32 IsPlayerOnHole(HoleManager*);
void DoHoleTransition(HoleManager*);
void HoleManager_UpdateParallaxBackground(HoleManager*);
void HoleManager_OnEnterRoom(HoleManager*);
void HoleManager_Init(HoleManager* this) {
const HoleTransition* transition;
Entity* obj;
SetEntityPriority((Entity*)super, PRIO_PLAYER_EVENT);
MemClear(&this->x, 0x20);
super->action = 1;
this->unk_3f = gRoomControls.room;
transition = &gHoleTransitions[super->type];
if (transition->hole_width == 0) {
this->x = gRoomControls.origin_x;
this->y = gRoomControls.origin_y;
this->width = gRoomControls.width;
this->height = gRoomControls.height;
} else {
this->x = (transition->hole_x << 4) + gRoomControls.origin_x;
this->y = (transition->hole_y << 4) + gRoomControls.origin_y;
this->width = (transition->hole_width << 4);
this->height = (transition->hole_height << 4);
}
super->type2 = transition->parallax_background != NULL;
if (super->type2) {
super->flags |= ENT_PERSIST;
this->persistance_offset_x = transition->parallax_background->offset_x;
this->persistance_offset_y = transition->parallax_background->offset_y;
this->persistance_x = transition->parallax_background->x;
this->persistance_y = transition->parallax_background->y;
UnDarkRoom();
HoleManager_UpdateParallaxBackground(this);
HoleManager_OnEnterRoom(this);
RegisterTransitionHandler(this, HoleManager_OnEnterRoom, NULL);
}
if (!transition->parallax_entity)
return;
obj = CreateObject(PARALLAX_ROOM_VIEW, transition->parallax_entity->type, transition->parallax_entity->subtype);
if (obj) {
obj->x.HALF.HI = transition->parallax_entity->x + gRoomControls.origin_x;
obj->y.HALF.HI = transition->parallax_entity->y + gRoomControls.origin_y;
}
if (super->type != 0xa || CheckLocalFlag(0x4B))
return;
obj = CreateObject(PARALLAX_ROOM_VIEW, 3, 3);
if (obj) {
obj->x.HALF.HI = transition->parallax_entity->x + gRoomControls.origin_x;
obj->y.HALF.HI = transition->parallax_entity->y + gRoomControls.origin_y;
}
}
void HoleManager_Update(HoleManager* this) {
if (IsPlayerOnHole(this)) {
DoHoleTransition(this);
DeleteThisEntity();
return;
}
HoleManager_UpdateParallaxBackground(this);
if (gRoomControls.reload_flags == 1) {
super->subAction = 1;
return;
}
if (super->subAction == 0)
return;
super->subAction = 0;
if (this->unk_3f == gRoomControls.room)
return;
if (super->type2) {
gScreen.lcd.displayControl &= ~0x800;
}
DeleteThisEntity();
}
bool32 IsPlayerOnHole(HoleManager* this) {
bool32 re = FALSE;
if (CheckPlayerProximity(this->x, this->y, this->width, this->height)) {
if ((gPlayerState.flags & PL_DROWNING) && (gPlayerState.flags & PL_BUSY)) {
gPlayerState.flags |= PL_PIT_IS_EXIT;
} else if (gPlayerState.flags & PL_PIT_IS_EXIT) {
re = TRUE;
}
}
return re;
}
void DoHoleTransition(HoleManager* this) {
const HoleTransition* transition;
gRoomTransition.transitioningOut = 1;
gRoomTransition.type = TRANSITION_CUT;
gRoomTransition.player_status.start_anim = 4;
transition = &gHoleTransitions[super->type];
gRoomTransition.player_status.area_next = transition->area;
gRoomTransition.player_status.room_next = transition->room;
gRoomTransition.player_status.layer = transition->layer;
if (gPlayerState.flags & PL_MINISH) {
gRoomTransition.player_status.spawn_type = PL_SPAWN_DROP_MINISH;
} else {
gRoomTransition.player_status.spawn_type = PL_SPAWN_DROP;
}
switch (transition->type) {
case HOLE_TRANSITION_ABSOLUTE:
gRoomTransition.player_status.start_pos_x = transition->x;
gRoomTransition.player_status.start_pos_y = transition->y;
break;
case HOLE_TRANSITION_RELATIVE:
gRoomTransition.player_status.start_pos_x =
gPlayerEntity.base.x.HALF.HI - gRoomControls.origin_x + transition->x;
gRoomTransition.player_status.start_pos_y =
gPlayerEntity.base.y.HALF.HI - gRoomControls.origin_y + transition->y;
break;
case HOLE_TRANSITION_ABSOLUTE_MINISH:
gRoomTransition.player_status.start_pos_x = transition->x;
gRoomTransition.player_status.start_pos_y = transition->y;
gRoomTransition.player_status.spawn_type = PL_SPAWN_DROP_MINISH;
break;
default:
break;
}
}
void HoleManager_UpdateParallaxBackground(HoleManager* this) {
s32 x, y;
if (!super->type2)
return;
x = (this->persistance_x - gRoomControls.scroll_x) / 4;
y = (this->persistance_y - gRoomControls.scroll_y) / 4;
if (x < -12) {
x = -12;
}
if (x > 12) {
x = 12;
}
if (y < -12) {
y = -12;
}
if (y > 12) {
y = 12;
}
gScreen.lcd.displayControl |= DISPCNT_BG3_ON;
gScreen.bg3.xOffset = gRoomControls.bg3OffsetX.HALF.HI = gRoomControls.scroll_x + this->persistance_offset_x + x;
gScreen.bg3.yOffset = gRoomControls.bg3OffsetY.HALF.HI = gRoomControls.scroll_y + this->persistance_offset_y + y;
}
void HoleManager_OnEnterRoom(HoleManager* this) {
const HoleTransition* transition;
if (!super->type2)
return;
transition = &gHoleTransitions[super->type];
LoadResourceAsync(&gGlobalGfxAndPalettes[transition->parallax_background->gfx], BG_SCREEN_ADDR(30), BG_SCREEN_SIZE);
gScreen.bg3.control = 0x1E07;
gScreen.lcd.displayControl |= DISPCNT_BG3_ON;
gScreen.bg3.xOffset = gRoomControls.bg3OffsetX.HALF.HI;
gScreen.bg3.yOffset = gRoomControls.bg3OffsetY.HALF.HI;
gScreen.controls.layerFXControl &= ~0x8;
}
void CreateHoleManager(u32 type) {
Manager* tmp = GetEmptyManager();
if (!tmp)
return;
tmp->kind = MANAGER;
tmp->id = HOLE_MANAGER;
tmp->type = type;
AppendEntityToList((Entity*)tmp, 6);
}