marioparty4/src/REL/present/present.c
2024-11-03 23:53:45 +01:00

1134 lines
39 KiB
C

#include "ext_math.h"
#include "game/esprite.h"
#include "game/gamework_data.h"
#include "game/hsfdraw.h"
#include "game/hsfex.h"
#include "game/hsfman.h"
#include "game/window.h"
#include "game/wipe.h"
#include "REL/present.h"
#define NUM_CHARACTERS 8
#define PRESENT_MDL_MAX 134
#define PRESENT_MAX 60
#define PRESENT_COUNT_CHAR_ROOM 6
#define PRESENT_COUNT_MG_ROOM 11
#define PRESENT_CONSTELLATION 5
#define ROOM_MARIO 0
#define ROOM_LUIGI 1
#define ROOM_PEACH 2
#define ROOM_YOSHI 3
#define ROOM_WARIO 4
#define ROOM_TROPHY 5
#define ROOM_DK 6
#define ROOM_DAISY 7
#define ROOM_WALUIGI 8
#define ROOM_MG 9
#define ROOM_MAX 9
#define ROOM_CHANGE_LEFT 1
#define ROOM_CHANGE_RIGHT 2
typedef struct PresentWork {
/* 0x00 */ BOOL cursorVisibleF;
/* 0x04 */ BOOL roomNotEmptyF;
/* 0x08 */ BOOL constellationSelF;
/* 0x0C */ s32 execMode;
/* 0x10 */ omObjData *object[PRESENT_MDL_MAX];
/* 0x228 */ PresentWindow *presentDescWindow;
/* 0x22C */ PresentWindow *btnLegendWindow;
/* 0x230 */ s16 cursor;
/* 0x234 */ s32 room;
/* 0x238 */ s32 idxInRoom;
/* 0x23C */ float rot;
/* 0x240 */ float rotPrev;
/* 0x244 */ float rotTarget;
/* 0x248 */ float timeRot;
/* 0x24C */ float presentFallingTime;
/* 0x250 */ float rotSpeed;
/* 0x254 */ float presentFallingSpeed;
/* 0x258 */ float cursorTime;
/* 0x25C */ float cursorSpeed;
/* 0x260 */ Vec2f cursorPos;
/* 0x268 */ Vec2f newCursorPos;
/* 0x270 */ BOOL presentUnlockedF[PRESENT_MAX];
/* 0x360 */ char unk360[4];
} PresentWork; /* size = 0x364 */
typedef struct UnkLightDataStruct {
/* 0x00 */ Vec src;
/* 0x0C */ Vec dest;
/* 0x18 */ GXColor color;
} UnkLightDataStruct; /* size = 0x1C */ // same as option::state::UnkLightDataStruct
typedef struct PresentData {
/* 0x00 */ s32 cursorPosIdx;
/* 0x04 */ s32 unk04;
/* 0x08 */ s32 nameMess;
/* 0x0C */ s32 descMess;
} PresentData; /* size = 0x10 */
typedef struct RoomData {
/* 0x00 */ s32 presentCount;
/* 0x04 */ PresentData presentData[11];
} RoomData; /* size = 0xB4 */
typedef struct PresentDistanceStruct {
/* 0x00 */ s32 present;
/* 0x04 */ float distance;
} PresentDistanceStruct; /* size = 0x08 */
static void ExecSelectRoom(omObjData *object);
static void ChangeRoom(omObjData *object, s32 direction);
static void ExecSelectPresent(omObjData *object);
static void GetCursorPos(omObjData *object, float *x, float *y, float *z);
static void SetCameraRot(omObjData *object, float rot, s32 duration);
static void RotateCamera(omObjData *object);
static BOOL CameraRotationDoneCheck(omObjData *object);
static void ShowHidePresents(omObjData *object);
static BOOL PresentUnlocked(omObjData *object, s32 room, s32 present);
static s32 UnlockedPresents(omObjData *object, s32 room);
static s32 MoveCursor(omObjData *object, s32 arg1);
static s32 TotalPresentsInRoom(s32 room);
static void ExecPresentGet(omObjData *object);
static s32 fn_1_393C(s32 arg0, s32 arg1);
static UnkLightDataStruct lightTbl = {
{ 0.0f, 400.0f, 0.0f },
{ 0.0f, -400.0f, -500.0f },
{ 255, 255, 255, 255 },
};
static omObjFunc execModeTbl[] = { NULL, ExecSelectRoom, ExecSelectPresent, ExecPresentGet };
static const s32 presentMdlTbl[PRESENT_MDL_MAX] = {
DATA_MAKE_NUM(DATADIR_PRESENT, 108),
DATA_MAKE_NUM(DATADIR_PRESENT, 107),
DATA_MAKE_NUM(DATADIR_PRESENT, 0),
DATA_MAKE_NUM(DATADIR_PRESENT, 1),
DATA_MAKE_NUM(DATADIR_PRESENT, 2),
DATA_MAKE_NUM(DATADIR_PRESENT, 3),
DATA_MAKE_NUM(DATADIR_PRESENT, 4),
DATA_MAKE_NUM(DATADIR_PRESENT, 5),
DATA_MAKE_NUM(DATADIR_PRESENT, 6),
DATA_MAKE_NUM(DATADIR_PRESENT, 7),
DATA_MAKE_NUM(DATADIR_PRESENT, 8),
DATA_MAKE_NUM(DATADIR_PRESENT, 9),
DATA_MAKE_NUM(DATADIR_PRESENT, 10),
DATA_MAKE_NUM(DATADIR_PRESENT, 11),
DATA_MAKE_NUM(DATADIR_PRESENT, 12),
DATA_MAKE_NUM(DATADIR_PRESENT, 13),
DATA_MAKE_NUM(DATADIR_PRESENT, 14),
DATA_MAKE_NUM(DATADIR_PRESENT, 15),
DATA_MAKE_NUM(DATADIR_PRESENT, 16),
DATA_MAKE_NUM(DATADIR_PRESENT, 17),
DATA_MAKE_NUM(DATADIR_PRESENT, 18),
DATA_MAKE_NUM(DATADIR_PRESENT, 19),
DATA_MAKE_NUM(DATADIR_PRESENT, 20),
DATA_MAKE_NUM(DATADIR_PRESENT, 21),
DATA_MAKE_NUM(DATADIR_PRESENT, 22),
DATA_MAKE_NUM(DATADIR_PRESENT, 23),
DATA_MAKE_NUM(DATADIR_PRESENT, 24),
DATA_MAKE_NUM(DATADIR_PRESENT, 25),
DATA_MAKE_NUM(DATADIR_PRESENT, 26),
DATA_MAKE_NUM(DATADIR_PRESENT, 27),
DATA_MAKE_NUM(DATADIR_PRESENT, 28),
DATA_MAKE_NUM(DATADIR_PRESENT, 29),
DATA_MAKE_NUM(DATADIR_PRESENT, 30),
DATA_MAKE_NUM(DATADIR_PRESENT, 31),
DATA_MAKE_NUM(DATADIR_PRESENT, 32),
DATA_MAKE_NUM(DATADIR_PRESENT, 33),
DATA_MAKE_NUM(DATADIR_PRESENT, 34),
DATA_MAKE_NUM(DATADIR_PRESENT, 35),
DATA_MAKE_NUM(DATADIR_PRESENT, 36),
DATA_MAKE_NUM(DATADIR_PRESENT, 37),
DATA_MAKE_NUM(DATADIR_PRESENT, 38),
DATA_MAKE_NUM(DATADIR_PRESENT, 39),
DATA_MAKE_NUM(DATADIR_PRESENT, 40),
DATA_MAKE_NUM(DATADIR_PRESENT, 41),
DATA_MAKE_NUM(DATADIR_PRESENT, 42),
DATA_MAKE_NUM(DATADIR_PRESENT, 43),
DATA_MAKE_NUM(DATADIR_PRESENT, 44),
DATA_MAKE_NUM(DATADIR_PRESENT, 45),
DATA_MAKE_NUM(DATADIR_PRESENT, 46),
DATA_MAKE_NUM(DATADIR_PRESENT, 47),
DATA_MAKE_NUM(DATADIR_PRESENT, 48),
DATA_MAKE_NUM(DATADIR_PRESENT, 49),
DATA_MAKE_NUM(DATADIR_PRESENT, 50),
DATA_MAKE_NUM(DATADIR_PRESENT, 51),
DATA_MAKE_NUM(DATADIR_PRESENT, 52),
DATA_MAKE_NUM(DATADIR_PRESENT, 53),
DATA_MAKE_NUM(DATADIR_PRESENT, 54),
DATA_MAKE_NUM(DATADIR_PRESENT, 55),
DATA_MAKE_NUM(DATADIR_PRESENT, 56),
DATA_MAKE_NUM(DATADIR_PRESENT, 57),
DATA_MAKE_NUM(DATADIR_PRESENT, 58),
DATA_MAKE_NUM(DATADIR_PRESENT, 59),
DATA_MAKE_NUM(DATADIR_PRESENT, 60),
DATA_MAKE_NUM(DATADIR_PRESENT, 61),
DATA_MAKE_NUM(DATADIR_PRESENT, 62),
DATA_MAKE_NUM(DATADIR_PRESENT, 63),
DATA_MAKE_NUM(DATADIR_PRESENT, 64),
DATA_MAKE_NUM(DATADIR_PRESENT, 65),
DATA_MAKE_NUM(DATADIR_PRESENT, 66),
DATA_MAKE_NUM(DATADIR_PRESENT, 67),
DATA_MAKE_NUM(DATADIR_PRESENT, 68),
DATA_MAKE_NUM(DATADIR_PRESENT, 69),
DATA_MAKE_NUM(DATADIR_PRESENT, 70),
DATA_MAKE_NUM(DATADIR_PRESENT, 71),
DATA_MAKE_NUM(DATADIR_PRESENT, 72),
DATA_MAKE_NUM(DATADIR_PRESENT, 73),
DATA_MAKE_NUM(DATADIR_PRESENT, 74),
DATA_MAKE_NUM(DATADIR_PRESENT, 75),
DATA_MAKE_NUM(DATADIR_PRESENT, 76),
DATA_MAKE_NUM(DATADIR_PRESENT, 77),
DATA_MAKE_NUM(DATADIR_PRESENT, 78),
DATA_MAKE_NUM(DATADIR_PRESENT, 79),
DATA_MAKE_NUM(DATADIR_PRESENT, 80),
DATA_MAKE_NUM(DATADIR_PRESENT, 81),
DATA_MAKE_NUM(DATADIR_PRESENT, 82),
DATA_MAKE_NUM(DATADIR_PRESENT, 83),
DATA_MAKE_NUM(DATADIR_PRESENT, 84),
DATA_MAKE_NUM(DATADIR_PRESENT, 85),
DATA_MAKE_NUM(DATADIR_PRESENT, 86),
DATA_MAKE_NUM(DATADIR_PRESENT, 87),
DATA_MAKE_NUM(DATADIR_PRESENT, 88),
DATA_MAKE_NUM(DATADIR_PRESENT, 89),
DATA_MAKE_NUM(DATADIR_PRESENT, 90),
DATA_MAKE_NUM(DATADIR_PRESENT, 91),
DATA_MAKE_NUM(DATADIR_PRESENT, 92),
DATA_MAKE_NUM(DATADIR_PRESENT, 93),
DATA_MAKE_NUM(DATADIR_PRESENT, 94),
DATA_MAKE_NUM(DATADIR_PRESENT, 95),
DATA_MAKE_NUM(DATADIR_PRESENT, 96),
DATA_MAKE_NUM(DATADIR_PRESENT, 97),
DATA_MAKE_NUM(DATADIR_PRESENT, 98),
DATA_MAKE_NUM(DATADIR_PRESENT, 99),
DATA_MAKE_NUM(DATADIR_PRESENT, 100),
DATA_MAKE_NUM(DATADIR_PRESENT, 101),
DATA_MAKE_NUM(DATADIR_PRESENT, 102),
DATA_MAKE_NUM(DATADIR_PRESENT, 103),
DATA_MAKE_NUM(DATADIR_PRESENT, 104),
DATA_MAKE_NUM(DATADIR_PRESENT, 105),
DATA_MAKE_NUM(DATADIR_PRESENT, 106),
DATA_MAKE_NUM(DATADIR_PRESENT, 109),
DATA_MAKE_NUM(DATADIR_PRESENT, 111),
DATA_MAKE_NUM(DATADIR_PRESENT, 113),
DATA_MAKE_NUM(DATADIR_PRESENT, 115),
DATA_MAKE_NUM(DATADIR_PRESENT, 117),
DATA_MAKE_NUM(DATADIR_PRESENT, 119),
DATA_MAKE_NUM(DATADIR_PRESENT, 121),
DATA_MAKE_NUM(DATADIR_PRESENT, 123),
DATA_MAKE_NUM(DATADIR_PRESENT, 125),
DATA_MAKE_NUM(DATADIR_PRESENT, 110),
DATA_MAKE_NUM(DATADIR_PRESENT, 112),
DATA_MAKE_NUM(DATADIR_PRESENT, 114),
DATA_MAKE_NUM(DATADIR_PRESENT, 116),
DATA_MAKE_NUM(DATADIR_PRESENT, 118),
DATA_MAKE_NUM(DATADIR_PRESENT, 120),
DATA_MAKE_NUM(DATADIR_PRESENT, 122),
DATA_MAKE_NUM(DATADIR_PRESENT, 124),
DATA_MAKE_NUM(DATADIR_PRESENT, 127),
DATA_MAKE_NUM(DATADIR_PRESENT, 128),
DATA_MAKE_NUM(DATADIR_PRESENT, 129),
DATA_MAKE_NUM(DATADIR_PRESENT, 130),
DATA_MAKE_NUM(DATADIR_PRESENT, 131),
DATA_MAKE_NUM(DATADIR_PRESENT, 132),
DATA_MAKE_NUM(DATADIR_PRESENT, 133),
DATA_MAKE_NUM(DATADIR_PRESENT, 134),
};
static const RoomData roomTbl[10] = {
{
0x00000006,
{
{ 0x00000002, 0x00000008, 0x00320006, 0x00320042 },
{ 0x00000003, 0x00000009, 0x00320007, 0x00320043 },
{ 0x00000004, 0x0000000A, 0x00320008, 0x00320044 },
{ 0x00000005, 0x0000000B, 0x00320009, 0x00320045 },
{ 0x00000006, 0x0000000C, 0x0032000A, 0x00320046 },
{ 0x00000007, 0x0000000D, 0x0032000B, 0x00320047 },
},
},
{
0x00000006,
{
{ 0x0000000E, 0x00000014, 0x0032000C, 0x00320048 },
{ 0x0000000F, 0x00000015, 0x0032000D, 0x00320049 },
{ 0x00000010, 0x00000016, 0x0032000E, 0x0032004A },
{ 0x00000011, 0x00000017, 0x0032000F, 0x0032004B },
{ 0x00000012, 0x00000018, 0x00320010, 0x0032004C },
{ 0x00000013, 0x00000019, 0x00320011, 0x0032004D },
},
},
{
0x00000006,
{
{ 0x0000001A, 0x00000020, 0x00320012, 0x0032004E },
{ 0x0000001B, 0x00000021, 0x00320013, 0x0032004F },
{ 0x0000001C, 0x00000022, 0x00320014, 0x00320050 },
{ 0x0000001D, 0x00000023, 0x00320015, 0x00320051 },
{ 0x0000001E, 0x00000024, 0x00320016, 0x00320052 },
{ 0x0000001F, 0x00000025, 0x00320017, 0x00320053 },
},
},
{
0x00000006,
{
{ 0x00000026, 0x0000002C, 0x00320018, 0x00320054 },
{ 0x00000027, 0x0000002D, 0x00320019, 0x00320055 },
{ 0x00000028, 0x0000002E, 0x0032001A, 0x00320056 },
{ 0x00000029, 0x0000002F, 0x0032001B, 0x00320057 },
{ 0x0000002A, 0x00000030, 0x0032001C, 0x00320058 },
{ 0x0000002B, 0x00000031, 0x0032001D, 0x00320059 },
},
},
{
0x00000006,
{
{ 0x00000032, 0x00000038, 0x0032001E, 0x0032005A },
{ 0x00000033, 0x00000039, 0x0032001F, 0x0032005B },
{ 0x00000034, 0x0000003A, 0x00320020, 0x0032005C },
{ 0x00000035, 0x0000003B, 0x00320021, 0x0032005D },
{ 0x00000036, 0x0000003C, 0x00320022, 0x0032005E },
{ 0x00000037, 0x0000003D, 0x00320023, 0x0032005F },
},
},
{
0x00000001,
{ { 0x00000001, 0xFFFFFFFF, 0x00320041, 0x00320041 } },
},
{
0x00000006,
{
{ 0x0000003E, 0x00000044, 0x00320024, 0x00320060 },
{ 0x0000003F, 0x00000045, 0x00320025, 0x00320061 },
{ 0x00000040, 0x00000046, 0x00320026, 0x00320062 },
{ 0x00000041, 0x00000047, 0x00320027, 0x00320063 },
{ 0x00000042, 0x00000048, 0x00320028, 0x00320064 },
{ 0x00000043, 0x00000049, 0x00320029, 0x00320065 },
},
},
{
0x00000006,
{
{ 0x0000004A, 0x00000050, 0x0032002A, 0x00320066 },
{ 0x0000004B, 0x00000051, 0x0032002B, 0x00320067 },
{ 0x0000004C, 0x00000052, 0x0032002C, 0x00320068 },
{ 0x0000004D, 0x00000053, 0x0032002D, 0x00320069 },
{ 0x0000004E, 0x00000054, 0x0032002E, 0x0032006A },
{ 0x0000004F, 0x00000055, 0x0032002F, 0x0032006B },
},
},
{
0x00000006,
{
{ 0x00000056, 0x0000005C, 0x00320030, 0x0032006C },
{ 0x00000057, 0x0000005D, 0x00320031, 0x0032006D },
{ 0x00000058, 0x0000005E, 0x00320032, 0x0032006E },
{ 0x00000059, 0x0000005F, 0x00320033, 0x0032006F },
{ 0x0000005A, 0x00000060, 0x00320034, 0x00320070 },
{ 0x0000005B, 0x00000061, 0x00320035, 0x00320071 },
},
},
{
0x0000000B,
{
{ 0x00000062, 0xFFFFFFFF, 0x00320036, 0x00320072 },
{ 0x00000063, 0xFFFFFFFF, 0x00320037, 0x00320073 },
{ 0x00000064, 0xFFFFFFFF, 0x00320038, 0x00320074 },
{ 0x00000065, 0xFFFFFFFF, 0x00320039, 0x00320075 },
{ 0x00000066, 0xFFFFFFFF, 0x0032003A, 0x00320076 },
{ 0x00000067, 0xFFFFFFFF, 0x0032003B, 0x00320077 },
{ 0x00000068, 0xFFFFFFFF, 0x0032003C, 0x00320078 },
{ 0x00000069, 0xFFFFFFFF, 0x0032003D, 0x00320079 },
{ 0x0000006A, 0xFFFFFFFF, 0x0032003E, 0x0032007A },
{ 0x0000006B, 0xFFFFFFFF, 0x0032003F, 0x0032007B },
{ 0x0000006C, 0xFFFFFFFF, 0x00320040, 0x0032007C },
},
},
};
omObjData *PresentCreate(void)
{
s32 i;
s32 j;
s16 light;
LightData *lightData;
omObjData *object = omAddObjEx(presentObjMan, 1003, 0, 0, 1, NULL);
PresentWork *work = HuMemDirectMallocNum(HEAP_SYSTEM, sizeof(PresentWork), MEMORY_DEFAULT_NUM);
object->data = work;
work->room = 0;
work->idxInRoom = 0;
work->rot = 0.0f;
work->timeRot = 1.0f;
work->rotSpeed = 0.0f;
for (i = 0; i < PRESENT_MAX; i++) {
work->presentUnlockedF[i] = GWGameStat.present[i];
}
for (i = 0; i < PRESENT_MAX - 1; i++) {
if (!work->presentUnlockedF[i]) {
break;
}
}
if (i == PRESENT_MAX - 1) {
work->presentUnlockedF[PRESENT_MAX - 1] = TRUE;
}
Hu3DLighInit();
light = Hu3DGLightCreateV(&lightTbl.src, &lightTbl.dest, &lightTbl.color);
Hu3DGLightInfinitytSet(light);
Hu3DGLightStaticSet(light, 1);
lightData = &Hu3DGlobalLight[light];
lightData->unk_00 |= 0x8000;
for (i = 0; i < PRESENT_MDL_MAX; i++) {
work->object[i] = omAddObjEx(presentObjMan, 1003, 1, 0, 1, NULL);
work->object[i]->model[0] = Hu3DModelCreateFile(presentMdlTbl[i]);
Hu3DModelLayerSet(work->object[i]->model[0], 0);
Hu3DModelAttrSet(work->object[i]->model[0], HU3D_ATTR_DISPOFF);
}
for (j = 0; j < 8; j++) {
for (i = 0; i < 6; i++) {
Hu3DModelLayerSet(work->object[i + 2 + j * 6 * 2]->model[0], 1);
}
}
Hu3DModelShadowMapSet(work->object[0]->model[0]);
ShowHidePresents(object);
work->cursor = espEntry(DATA_MAKE_NUM(DATADIR_PRESENT, 135), 0, 0);
espDispOff(work->cursor);
work->presentDescWindow = PresentWinCreate(0);
work->btnLegendWindow = PresentWinCreate(1);
SetCameraRot(object, work->room * 36.0f, 1);
RotateCamera(object);
PresentExecModeSet(object, PRESENT_MODE_NONE);
(void)light;
return object;
}
void PresentKill(omObjData *object)
{
s32 i;
PresentWork *work = object->data;
PresentWinKill(work->presentDescWindow);
PresentWinKill(work->btnLegendWindow);
for (i = 0; i < PRESENT_MDL_MAX; i++) {
Hu3DModelKill(work->object[i]->model[0]);
}
espKill(work->cursor);
HuMemDirectFree(work);
}
void PresentExecModeSet(omObjData *object, s32 execMode)
{
PresentWork *work = object->data;
work->execMode = execMode;
object->func = execModeTbl[execMode];
object->unk10 = 0;
object->unk10 = 0;
}
s32 PresentExecModeGet(omObjData *object)
{
PresentWork *work = object->data;
return work->execMode;
}
static const s32 roomIdxTbl[NUM_CHARACTERS] = {
ROOM_MARIO,
ROOM_LUIGI,
ROOM_PEACH,
ROOM_YOSHI,
ROOM_WARIO,
ROOM_DK,
ROOM_DAISY,
ROOM_WALUIGI,
};
void PresentSelectedIDSet(omObjData *object, s32 id)
{
PresentWork *work = object->data;
if (id < 48) {
work->room = roomIdxTbl[id / PRESENT_COUNT_CHAR_ROOM];
work->idxInRoom = id % PRESENT_COUNT_CHAR_ROOM;
return;
}
if (id < 59) {
work->room = ROOM_MG;
work->idxInRoom = (id - 48) % PRESENT_COUNT_MG_ROOM;
return;
}
work->room = ROOM_TROPHY;
work->idxInRoom = 0;
}
static const s32 roomMessTbl[] = { 0, 1, 2, 3, 4, 0, 5, 6, 7, 0 };
static void ExecSelectRoom(omObjData *object)
{
Vec cursorPos;
s32 mess;
PresentWork *work = object->data;
switch (object->unk10) {
case 0:
work->cursorVisibleF = FALSE;
work->constellationSelF = FALSE;
object->unk10 = 1;
case 1:
if (work->constellationSelF) {
PresentCameraTargetSet(presentCamera, 0.0f, 220.0f, 250.0f, 30);
PresentCameraFocusSet(presentCamera, 0.0f, 420.0f, -600.0f, 30);
}
else {
PresentCameraTargetSet(presentCamera, 0.0f, 220.0f, 250.0f, 30);
PresentCameraFocusSet(presentCamera, 0.0f, 0.0f, -600.0f, 30);
}
object->unk10 = 2;
case 2:
if (!PresentCameraDoneCheck(presentCamera) && !work->presentDescWindow->state && !CameraRotationDoneCheck(object)) {
PresentWinAnimIn(work->presentDescWindow);
PresentWinAnimIn(work->btnLegendWindow);
if (work->constellationSelF) {
mess = MAKE_MESSID(0x32, 0x80);
}
else if (work->room == ROOM_TROPHY) {
mess = MAKE_MESSID(0x32, 0x85);
}
else {
mess = MAKE_MESSID(0x32, 0x7e);
}
PresentWinMesSet(work->btnLegendWindow, mess);
switch (work->room) {
case ROOM_MARIO:
case ROOM_LUIGI:
case ROOM_PEACH:
case ROOM_YOSHI:
case ROOM_WARIO:
case ROOM_DK:
case ROOM_DAISY:
case ROOM_WALUIGI:
if (work->constellationSelF) {
if (PresentUnlocked(object, work->room, ROOM_TROPHY)) {
mess = MAKE_MESSID(0x32, 0x05);
}
else {
mess = MAKE_MESSID(0x32, 0x82);
}
}
else if (UnlockedPresents(object, work->room) > 0) {
mess = MAKE_MESSID(0x32, 0x01);
}
else {
mess = MAKE_MESSID(0x32, 0x81);
}
PresentWinMesSet(work->presentDescWindow, mess);
PresentWinInsertMesSet(work->presentDescWindow, roomMessTbl[work->room], 0);
break;
case ROOM_TROPHY:
if (PresentUnlocked(object, ROOM_TROPHY, 0)) {
mess = MAKE_MESSID(0x32, 0x41);
}
else {
mess = MAKE_MESSID(0x32, 0x84);
}
PresentWinMesSet(work->presentDescWindow, mess);
break;
case ROOM_MG:
if (UnlockedPresents(object, ROOM_MG) > 0) {
mess = MAKE_MESSID(0x32, 0x83);
}
else {
mess = MAKE_MESSID(0x32, 0x81);
}
PresentWinMesSet(work->presentDescWindow, mess);
break;
default:
break;
}
if (work->constellationSelF) {
cursorPos.x = 0.0f;
cursorPos.y = 600.0f;
cursorPos.z = -500.0f;
}
else {
cursorPos.x = 0.0f;
cursorPos.y = 210.0f;
cursorPos.z = -500.0f;
}
Hu3D3Dto2D(&cursorPos, 1, &cursorPos);
cursorPos.y -= 15.0f;
cursorPos.x -= 20.0f;
espPosSet(work->cursor, cursorPos.x, cursorPos.y);
if (!work->cursorVisibleF) {
PresentFadeSprite(work->cursor, TRUE, 5);
work->cursorVisibleF = TRUE;
}
object->unk10 = 3;
}
break;
case 3:
if (!work->presentDescWindow->state) {
if (PresentPadCheck(PAD_BUTTON_B) && !work->constellationSelF) {
PresentFadeSprite(work->cursor, FALSE, 5);
work->cursorVisibleF = FALSE;
PresentWinAnimOut(work->presentDescWindow);
PresentWinAnimOut(work->btnLegendWindow);
HuAudFXPlay(3);
object->unk10 = 4;
}
else if (PresentPadCheck(PAD_BUTTON_A) && !work->constellationSelF) {
if (work->room != ROOM_TROPHY) {
PresentFadeSprite(work->cursor, FALSE, 5);
work->cursorVisibleF = FALSE;
PresentWinAnimOut(work->presentDescWindow);
PresentWinAnimOut(work->btnLegendWindow);
HuAudFXPlay(2);
PresentExecModeSet(object, PRESENT_MODE_SELECT_PRESENT);
}
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_UP) && !work->constellationSelF) {
if (work->room != ROOM_TROPHY && work->room != ROOM_MG) {
work->constellationSelF = TRUE;
PresentFadeSprite(work->cursor, FALSE, 5);
work->cursorVisibleF = FALSE;
PresentWinAnimOut(work->presentDescWindow);
PresentWinAnimOut(work->btnLegendWindow);
HuAudFXPlay(0);
object->unk10 = 1;
}
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_DOWN) && work->constellationSelF) {
work->constellationSelF = FALSE;
PresentFadeSprite(work->cursor, FALSE, 5);
work->cursorVisibleF = FALSE;
PresentWinAnimOut(work->presentDescWindow);
PresentWinAnimOut(work->btnLegendWindow);
HuAudFXPlay(0);
object->unk10 = 1;
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_LEFT)) {
ChangeRoom(object, ROOM_CHANGE_LEFT);
HuAudFXPlay(0);
object->unk10 = 2;
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_RIGHT)) {
ChangeRoom(object, ROOM_CHANGE_RIGHT);
HuAudFXPlay(0);
object->unk10 = 2;
}
}
break;
case 4:
PresentExecModeSet(object, PRESENT_MODE_NONE);
break;
}
RotateCamera(object);
}
static void ChangeRoom(omObjData *object, s32 direction)
{
float rotAbs;
float rot;
float rotTarget;
s32 special;
s32 change;
s32 duration;
PresentWork *work = object->data;
for (special = 0, rotAbs = 0.0f;; special++) {
rotAbs += 36.0f;
if (direction == ROOM_CHANGE_LEFT) {
change = -1;
}
else {
change = 1;
}
work->room += change;
if (work->room < ROOM_MARIO) {
work->room = ROOM_MAX;
}
else if (work->room >= ROOM_MAX + 1) {
work->room = ROOM_MARIO;
}
if (!work->constellationSelF || (work->room != ROOM_TROPHY && work->room != ROOM_MG)) {
break;
}
}
if (direction == ROOM_CHANGE_LEFT) {
rot = -rotAbs;
}
else {
rot = rotAbs;
}
rotTarget = work->rot + rot;
if (special == 0) {
duration = 30;
}
else {
duration = 45;
}
SetCameraRot(object, rotTarget, duration);
}
static void ExecSelectPresent(omObjData *object)
{
float cursorX;
float cursorY;
PresentWork *work = object->data;
s32 idxInRoom = work->idxInRoom;
s32 room = work->room;
switch (object->unk10) {
case 0:
PresentCameraTargetSet(presentCamera, 0.0f, 220.0f, -120.0f, 30);
PresentCameraFocusSet(presentCamera, 0.0f, 0.0f, -600.0f, 30);
work->roomNotEmptyF = UnlockedPresents(object, room) > 0;
work->cursorVisibleF = FALSE;
work->idxInRoom = 0;
if (work->roomNotEmptyF) {
s32 totalPresents = TotalPresentsInRoom(work->room);
s32 i;
// set the initial present to the highest unlocked one
for (i = 0; i < totalPresents; i++) {
if (PresentUnlocked(object, room, i)) {
work->idxInRoom = i;
break;
}
}
}
object->unk10 = 1;
case 1:
if (PresentCameraDoneCheck(presentCamera)) {
break;
}
PresentWinAnimIn(work->presentDescWindow);
PresentWinAnimIn(work->btnLegendWindow);
PresentWinMesSet(work->btnLegendWindow, MAKE_MESSID(0x32, 0x7F));
if (work->roomNotEmptyF) {
PresentWinMesSet(work->presentDescWindow, roomTbl[room].presentData[idxInRoom].descMess);
}
else {
PresentWinMesSet(work->presentDescWindow, MAKE_MESSID(0x32, 0x03));
}
work->cursorTime = 0.0f;
work->cursorSpeed = 1.0f / 6.0f;
if (work->roomNotEmptyF) {
Vec cursorPos;
GetCursorPos(work->object[roomTbl[room].presentData[idxInRoom].cursorPosIdx], &cursorPos.x, &cursorPos.y, &cursorPos.z);
Hu3D3Dto2D(&cursorPos, 1, &cursorPos);
cursorPos.y -= 15.0f;
cursorPos.x -= 20.0f;
if (!work->cursorVisibleF) {
PresentFadeSprite(work->cursor, TRUE, 5);
work->cursorVisibleF = TRUE;
work->cursorPos.x = cursorPos.x;
work->cursorPos.y = cursorPos.y;
}
else {
work->cursorPos.x = work->newCursorPos.x;
work->cursorPos.y = work->newCursorPos.y;
}
work->newCursorPos.x = cursorPos.x;
work->newCursorPos.y = cursorPos.y;
object->unk10 = 2;
}
else {
object->unk10 = 3;
break;
}
case 2:
cursorX = work->cursorPos.x + (work->cursorTime * (work->newCursorPos.x - work->cursorPos.x));
cursorY = work->cursorPos.y + (work->cursorTime * (work->newCursorPos.y - work->cursorPos.y));
espPosSet(work->cursor, cursorX, cursorY);
if ((work->cursorTime += work->cursorSpeed) < 1.0f) {
break;
}
espPosSet(work->cursor, work->newCursorPos.x, work->newCursorPos.y);
object->unk10 = 3;
case 3:
if (PresentPadCheck(PAD_BUTTON_B)) {
PresentWinAnimOut(work->presentDescWindow);
PresentWinAnimOut(work->btnLegendWindow);
HuAudFXPlay(3);
object->unk10 = 4;
}
else if (work->roomNotEmptyF) {
if (PresentPadDStkRepCheck(PAD_BUTTON_LEFT) && PresentPadDStkCheck(PAD_BUTTON_UP)) {
idxInRoom = MoveCursor(object, 5);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_LEFT) && PresentPadDStkCheck(PAD_BUTTON_DOWN)) {
idxInRoom = MoveCursor(object, 9);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_RIGHT) && PresentPadDStkCheck(PAD_BUTTON_UP)) {
idxInRoom = MoveCursor(object, 6);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_RIGHT) && PresentPadDStkCheck(PAD_BUTTON_DOWN)) {
idxInRoom = MoveCursor(object, 10);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_LEFT)) {
idxInRoom = MoveCursor(object, 1);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_RIGHT)) {
idxInRoom = MoveCursor(object, 2);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_UP)) {
idxInRoom = MoveCursor(object, 4);
}
else if (PresentPadDStkRepCheck(PAD_BUTTON_DOWN)) {
idxInRoom = MoveCursor(object, 8);
}
}
else {
break;
}
if (idxInRoom == -1) {
idxInRoom = work->idxInRoom;
}
if (idxInRoom != work->idxInRoom) {
work->idxInRoom = idxInRoom;
object->unk10 = 1;
HuAudFXPlay(0);
}
break;
case 4:
if (work->cursorVisibleF) {
PresentFadeSprite(work->cursor, FALSE, 5);
}
PresentExecModeSet(object, PRESENT_MODE_SELECT_ROOM);
break;
default:
break;
}
}
static void GetCursorPos(omObjData *object, float *x, float *y, float *z)
{
Mtx sp8;
Hu3DModelObjMtxGet(object->model[0], "cursor", sp8);
*x = sp8[0][3];
*y = sp8[1][3];
*z = sp8[2][3];
}
static void SetCameraRot(omObjData *object, float rot, s32 duration)
{
PresentWork *work = object->data;
work->rotTarget = rot;
work->rotPrev = work->rot;
work->timeRot = 0.0f;
work->rotSpeed = 1.0f / duration;
}
static void RotateCamera(omObjData *object)
{
s32 i;
PresentWork *work = object->data;
if (work->timeRot < 1.0f) {
float weight = sind(90.0f * work->timeRot);
weight *= weight;
work->rot = work->rotPrev + (weight * (work->rotTarget - work->rotPrev));
if ((work->timeRot += work->rotSpeed) >= 1.0f) {
work->rot = work->rotTarget;
}
}
work->rot = fmod(work->rot, 360.0);
if (work->rot < 0.0f) {
work->rot += 360.0f;
}
for (i = 0; i < PRESENT_MDL_MAX; i++) {
omSetRot(work->object[i], 0.0f, work->rot, 0.0f);
}
}
static BOOL CameraRotationDoneCheck(omObjData *object)
{
PresentWork *work = object->data;
return work->timeRot < 1.0f;
}
s32 roomIdxTbl2[NUM_CHARACTERS] = {
ROOM_MARIO,
ROOM_LUIGI,
ROOM_PEACH,
ROOM_YOSHI,
ROOM_WARIO,
ROOM_DK,
ROOM_DAISY,
ROOM_WALUIGI,
};
static void ShowHidePresents(omObjData *object)
{
PresentWork *work = object->data;
s32 character;
s32 i;
Hu3DModelAttrReset(work->object[0]->model[0], HU3D_ATTR_DISPOFF);
for (character = 0; character < NUM_CHARACTERS; character++) {
s32 j;
if (UnlockedPresents(object, roomIdxTbl2[character]) > 0) {
Hu3DModelAttrReset(work->object[character + 109]->model[0], HU3D_ATTR_DISPOFF);
}
for (j = 0, i = 0; i < PRESENT_COUNT_CHAR_ROOM; i++) {
if (PresentUnlocked(object, roomIdxTbl2[character], i)) {
Hu3DModelAttrReset(work->object[character * PRESENT_COUNT_CHAR_ROOM * 2 + 2 + i]->model[0], HU3D_ATTR_DISPOFF);
Hu3DModelAttrReset(work->object[character * PRESENT_COUNT_CHAR_ROOM * 2 + 8 + i]->model[0], HU3D_ATTR_DISPOFF);
j++;
}
}
if (j >= 6) {
Hu3DModelAttrReset(work->object[character + 118]->model[0], HU3D_ATTR_DISPOFF);
}
}
if (UnlockedPresents(object, ROOM_MG) > 0) {
Hu3DModelAttrReset(work->object[117]->model[0], HU3D_ATTR_DISPOFF);
}
for (i = 0; i < PRESENT_COUNT_MG_ROOM; i++) {
if (PresentUnlocked(object, ROOM_MG, i)) {
Hu3DModelAttrReset(work->object[i + 98]->model[0], HU3D_ATTR_DISPOFF);
}
}
if (PresentUnlocked(object, ROOM_TROPHY, 0)) {
Hu3DModelAttrReset(work->object[1]->model[0], HU3D_ATTR_DISPOFF);
}
for (i = 0; i < NUM_CHARACTERS; i++) {
if (PresentUnlocked(object, roomIdxTbl2[i], PRESENT_CONSTELLATION)) {
Hu3DModelAttrReset(work->object[i + 126]->model[0], HU3D_ATTR_DISPOFF);
}
}
}
static const s32 roomPresentOffsetTbl[] = { 0, 6, 12, 18, 24, 59, 30, 36, 42, 48 };
static BOOL PresentUnlocked(omObjData *object, s32 room, s32 present)
{
PresentWork *work = object->data;
return work->presentUnlockedF[roomPresentOffsetTbl[room] + present] != 0;
}
static s32 UnlockedPresents(omObjData *object, s32 room)
{
s32 i;
s32 unlockedPresents;
s32 presentCount = TotalPresentsInRoom(room);
for (unlockedPresents = 0, i = 0; i < presentCount; i++) {
if (PresentUnlocked(object, room, i)) {
unlockedPresents++;
}
}
return unlockedPresents;
}
/* Returns the index of the newly selected present inside the room */
static s32 MoveCursor(omObjData *object, s32 arg1)
{
PresentDistanceStruct availablePresents[10];
Vec cursorPos;
float angle;
PresentWork *work = object->data;
s32 present;
s32 i;
s32 j;
s32 var_r23;
s32 totalPresents = TotalPresentsInRoom(work->room);
s32 unlockedPresents = UnlockedPresents(object, work->room);
if (unlockedPresents == 1) {
return work->idxInRoom;
}
GetCursorPos(work->object[roomTbl[work->room].presentData[work->idxInRoom].cursorPosIdx], &cursorPos.x, &cursorPos.y, &cursorPos.z);
Hu3D3Dto2D(&cursorPos, 1, &cursorPos);
for (i = 0, j = 0; i == 0 && j < 1; j++) {
for (i = 0, present = 0; present < totalPresents; present++) {
Vec cursorPosNew;
float dx, dy;
if (present == work->idxInRoom) {
continue;
}
if (!PresentUnlocked(object, work->room, present)) {
continue;
}
GetCursorPos(work->object[roomTbl[work->room].presentData[present].cursorPosIdx], &cursorPosNew.x, &cursorPosNew.y, &cursorPosNew.z);
Hu3D3Dto2D(&cursorPosNew, 1, &cursorPosNew);
dx = cursorPos.x - cursorPosNew.x;
dy = cursorPos.y - cursorPosNew.y;
angle = fmod(atan2d(dx, dy), 360.0);
if (angle < 0.0f) {
angle += 360.0f;
}
if ((arg1 == 1 && angle >= 45.0f && angle < 135.0f) || (arg1 == 2 && angle >= 225.0f && angle < 315.0f)
|| (arg1 == 8 && angle >= 135.0f && angle < 225.0f)
|| (arg1 == 4 && (angle >= 0.0f && angle < 45.0f || angle >= 315.0f && angle < 360.0f))
|| (arg1 == 5 && angle >= 0.0f && angle < 90.0f) || (arg1 == 9 && angle >= 90.0f && angle < 180.0f)
|| (arg1 == 6 && angle >= 270.0f && angle < 360.0f) || (arg1 == 10 && angle >= 180.0f && angle < 270.0f)) {
availablePresents[i].present = present;
availablePresents[i].distance = sqrtf(dx * dx + dy * dy);
i++;
}
}
if (i != 0) {
continue;
}
switch (arg1) {
case 0:
break;
case 1:
arg1 = 2;
break;
case 2:
arg1 = 1;
break;
case 3:
break;
case 4:
arg1 = 8;
break;
case 7:
break;
case 8:
arg1 = 4;
break;
case 5:
arg1 = 10;
break;
case 9:
arg1 = 6;
break;
case 6:
arg1 = 9;
break;
case 10:
arg1 = 5;
break;
default:
break;
}
}
if (i == 0) {
return work->idxInRoom;
}
do {
for (var_r23 = 0, present = 0; present < (i - 1); present++) {
if (availablePresents[present].distance > availablePresents[present + 1].distance) {
PresentDistanceStruct next = availablePresents[present + 1];
availablePresents[present + 1] = availablePresents[present];
availablePresents[present] = next;
var_r23 = 1;
}
}
} while (var_r23);
return availablePresents[(j <= 1) ? 0 : i - 1].present;
}
static const s32 totalPresentCntTbl[10] = { 6, 6, 6, 6, 6, 1, 6, 6, 6, 11 };
static s32 TotalPresentsInRoom(s32 room)
{
return totalPresentCntTbl[room];
}
static const s32 presentItemIdxTbl[10] = { 2, 14, 26, 38, 50, 0, 62, 74, 86, 0 };
static const s32 lbl_1_rodata_B18[10] = { 8, 20, 32, 44, 56, 0, 68, 80, 92, 0 };
static const s32 constellationIdxTbl[10] = { 126, 127, 128, 129, 130, 0, 131, 132, 133, 0 };
static const s32 roofIdxTbl[10] = { 118, 119, 120, 121, 122, 0, 123, 124, 125, 0 };
static void ExecPresentGet(omObjData *object)
{
f32 weight;
f32 rot;
PresentWork *work = object->data;
switch (object->unk10) {
case 0:
rot = 36.0f * work->room;
SetCameraRot(object, rot, 1);
RotateCamera(object);
Hu3DModelAttrSet(work->object[work->idxInRoom + lbl_1_rodata_B18[work->room]]->model[0], HU3D_ATTR_DISPOFF);
Hu3DModelAttrSet(work->object[roofIdxTbl[work->room]]->model[0], HU3D_ATTR_DISPOFF);
Hu3DModelAttrSet(work->object[constellationIdxTbl[work->room]]->model[0], HU3D_ATTR_DISPOFF);
work->presentFallingTime = 0.0f;
work->presentFallingSpeed = 1.0f / 360.0f;
object->unk10 = 1;
case 1:
WipeCreate(WIPE_MODE_IN, WIPE_TYPE_NORMAL, 120);
object->unk10 = 2;
case 2:
weight = sind(90.0f * work->presentFallingTime);
weight *= weight;
PresentCameraTargetSet(presentCamera, 0.0f, 820.0f - (600.0f * weight), -120.0f, 1);
PresentCameraFocusSet(presentCamera, 0.0f, 680.0f - (680.0f * weight), -600.0f, 1);
omSetTra(work->object[work->idxInRoom + presentItemIdxTbl[work->room]], 0.0f, 840.0f - (840.0f * weight), 0.0f);
if ((work->presentFallingTime += work->presentFallingSpeed) < 1.0f) {
return;
}
if (fn_1_393C(work->room, work->idxInRoom)) {
FadeSpriteWithMultiplier(work->object[work->idxInRoom + lbl_1_rodata_B18[work->room]]->model[0], 1, 0.4f, 30);
}
object->unk10 = 3;
case 3:
PresentWinAnimIn(work->presentDescWindow);
PresentWinInsertMesSet(work->presentDescWindow, roomTbl[work->room].presentData[work->idxInRoom].nameMess, 0);
PresentWinMesSet(work->presentDescWindow, MAKE_MESSID(0x32, 0x04));
PresentWinMesWait(work->presentDescWindow);
object->unk10 = 4;
case 4:
if (work->presentDescWindow->state) {
break;
}
object->unk10 = 5;
case 5:
PresentWinAnimOut(work->presentDescWindow);
object->unk10 = 6;
case 6:
if (!work->presentDescWindow->state) {
PresentExecModeSet(object, PRESENT_MODE_NONE);
}
break;
}
}
static const s32 lbl_1_rodata_BA4[][2] = { { 7, 1 } };
static s32 fn_1_393C(s32 arg0, s32 arg1)
{
s32 var_r31;
for (var_r31 = 0; var_r31 < 1; var_r31++) {
if (arg0 == lbl_1_rodata_BA4[var_r31][0] && arg1 == lbl_1_rodata_BA4[var_r31][1]) {
return 0;
}
}
return 1;
}