diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 385ef1b7..3a437fd8 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2462,6 +2462,9 @@ CUTSCENE_LOOP = 0x7FFF --- @type integer CUTSCENE_NONPAINTING_DEATH = 170 +--- @type integer +CUTSCENE_PALETTE_EDITOR = 182 + --- @type integer CUTSCENE_PREPARE_CANNON = 150 @@ -8797,6 +8800,9 @@ ACT_SUFFOCATION = 0x00021314 --- @type integer ACT_SWIMMING_END = 0x300024D1 +--- @type integer +ACT_TAKING_OFF_CAP = 0x0000133E + --- @type integer ACT_TELEPORT_FADE_IN = 0x00001337 diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 58a18b4f..5ff48a20 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -219,6 +219,7 @@ --- @field public mode integer --- @field public mtx Mat4 --- @field public nextYaw integer +--- @field public paletteEditorCap boolean --- @field public pos Vec3f --- @field public unusedVec1 Vec3f --- @field public yaw integer diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 74b96bd4..f483010c 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -777,6 +777,7 @@ - CUTSCENE_KEY_DANCE - CUTSCENE_LOOP - CUTSCENE_NONPAINTING_DEATH +- CUTSCENE_PALETTE_EDITOR - CUTSCENE_PREPARE_CANNON - CUTSCENE_QUICKSAND_DEATH - CUTSCENE_RACE_DIALOG @@ -3144,6 +3145,7 @@ - ACT_STOP_CROUCHING - ACT_SUFFOCATION - ACT_SWIMMING_END +- ACT_TAKING_OFF_CAP - ACT_TELEPORT_FADE_IN - ACT_TELEPORT_FADE_OUT - ACT_THROWING diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 6925c3f8..333e5d24 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -365,6 +365,7 @@ | mode | `integer` | | | mtx | `Mat4` | read-only | | nextYaw | `integer` | | +| paletteEditorCap | `boolean` | | | pos | [Vec3f](structs.md#Vec3f) | read-only | | unusedVec1 | [Vec3f](structs.md#Vec3f) | read-only | | yaw | `integer` | | diff --git a/include/sm64.h b/include/sm64.h index 80bdd25b..b3a2c68a 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -396,6 +396,7 @@ #define ACT_BUTT_STUCK_IN_GROUND 0x0002033B // (0x13B | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE) #define ACT_FEET_STUCK_IN_GROUND 0x0002033C // (0x13C | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE) #define ACT_PUTTING_ON_CAP 0x0000133D // (0x13D | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE) +#define ACT_TAKING_OFF_CAP 0x0000133E // (0x13E | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE) // ! COOP ACTION // group 0x140: "automatic" actions #define ACT_HOLDING_POLE 0x08100340 // (0x140 | ACT_FLAG_STATIONARY | ACT_FLAG_ON_POLE | ACT_FLAG_PAUSE_EXIT) diff --git a/src/game/camera.c b/src/game/camera.c index 63215367..0b5f5fc2 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -28,6 +28,7 @@ #include "paintings.h" #include "engine/graph_node.h" #include "level_table.h" +#include "mario.h" #include "game/hardcoded.h" #include "game/sound_init.h" #include "pc/configfile.h" @@ -472,6 +473,8 @@ s32 update_slide_or_0f_camera(struct Camera *c, Vec3f, Vec3f); s32 update_spiral_stairs_camera(struct Camera *c, Vec3f, Vec3f); s32 update_rom_hack_camera(struct Camera *c, Vec3f, Vec3f); void mode_rom_hack_camera(struct Camera *c); +void cutscene_take_cap_off(struct MarioState *m); +void cutscene_put_cap_on(struct MarioState *m); typedef s32 (*CameraTransition)(struct Camera *c, Vec3f, Vec3f); CameraTransition sModeTransitions[] = { @@ -3343,6 +3346,12 @@ void update_camera(struct Camera *c) { update_lakitu(c); gLakituState.lastFrameAction = sMarioCamState->action; + + // Make sure the palette editor cutscene is properly reset + if (c->paletteEditorCap && c->cutscene != CUTSCENE_PALETTE_EDITOR && (gMarioState->flags & MARIO_CAP_ON_HEAD) == 0) { + cutscene_put_cap_on(gMarioState); + c->paletteEditorCap = false; + } } void soft_reset_camera(struct Camera* c) { @@ -10849,6 +10858,35 @@ BAD_RETURN(s32) cutscene_door_mode(struct Camera *c) { } } +// coop specific +void cutscene_palette_editor(struct Camera *c) { + if (!c) { return; } + struct MarioState* m = gMarioState; + + if (!gInPlayerMenu) { + if (c->paletteEditorCap) { + if (!(m->flags & MARIO_CAP_ON_HEAD)) { + set_mario_action(m, ACT_PUTTING_ON_CAP, 0); + } + c->paletteEditorCap = false; + } + c->cutscene = 0; + return; + } + if (m->action == ACT_IDLE && m->flags & MARIO_CAP_ON_HEAD) { + set_mario_action(m, ACT_TAKING_OFF_CAP, 0); + c->paletteEditorCap = true; + } + + c->pos[0] = m->pos[0] + (0x200 * sins(m->faceAngle[1])); + c->pos[1] = m->pos[1] + 0x80; + c->pos[2] = m->pos[2] + (0x200 * coss(m->faceAngle[1])); + + c->focus[0] = m->pos[0]; + c->focus[1] = m->pos[1] + 0x80; + c->focus[2] = m->pos[2]; +} + /****************************************************************************************************** * Cutscenes ******************************************************************************************************/ @@ -11247,6 +11285,10 @@ struct Cutscene sCutsceneReadMessage[] = { { cutscene_read_message_end, 0 } }; +struct Cutscene sCutscenePaletteEditor[] = { + { cutscene_palette_editor, CUTSCENE_LOOP }, +}; + /* TODO: * The next two arrays are both related to levels, and they look generated. * These should be split into their own file. @@ -11720,6 +11762,7 @@ void play_cutscene(struct Camera *c) { CUTSCENE(CUTSCENE_RACE_DIALOG, sCutsceneDialog) CUTSCENE(CUTSCENE_ENTER_PYRAMID_TOP, sCutsceneEnterPyramidTop) CUTSCENE(CUTSCENE_SSL_PYRAMID_EXPLODE, sCutscenePyramidTopExplode) + CUTSCENE(CUTSCENE_PALETTE_EDITOR, sCutscenePaletteEditor) } #undef CUTSCENE diff --git a/src/game/camera.h b/src/game/camera.h index 217ad751..20f8cbaa 100644 --- a/src/game/camera.h +++ b/src/game/camera.h @@ -257,6 +257,7 @@ extern u8 gRomhackCameraAllowDpad; #define CUTSCENE_EXIT_WATERFALL 179 #define CUTSCENE_EXIT_FALL_WMOTR 180 #define CUTSCENE_ENTER_POOL 181 +#define CUTSCENE_PALETTE_EDITOR 182 /** * Stop the cutscene. @@ -575,6 +576,7 @@ struct Camera /// when paused. See zoom_out_if_paused_and_outside /*0x68*/ f32 areaCenY; /*????*/ Mat4 mtx; + /*????*/ bool paletteEditorCap; }; /** diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index a10ce041..53e717c5 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -3154,7 +3154,7 @@ s16 render_pause_courses_and_castle(void) { gDialogTextAlpha += 25; } - if (gDjuiPanelPauseCreated) { shade_screen(); } + if (gDjuiPanelPauseCreated && !gInPlayerMenu) { shade_screen(); } if (gPlayer1Controller->buttonPressed & R_TRIG) { djui_panel_pause_create(NULL); } diff --git a/src/game/level_update.c b/src/game/level_update.c index c2535546..4fee9d4b 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1646,6 +1646,12 @@ void update_menu_level(void) { gMarioState->faceAngle[1] = -0x1C34; break; } + gLakituState.skipCameraInterpolationTimestamp = gGlobalTimer; + extern s32 gCamSkipInterp; + gCamSkipInterp = 1; + vec3f_copy(gCurrentArea->camera->pos, gLakituState.curPos); + vec3f_copy(gLakituState.pos, gLakituState.curPos); + vec3f_copy(gLakituState.goalPos, gLakituState.curPos); gMarioState->health = 0x880; // reset input diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index a0ec7b8d..30a101b0 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -1847,7 +1847,7 @@ s32 act_squished(struct MarioState *m) { s32 act_putting_on_cap(struct MarioState *m) { s32 animFrame = set_character_animation(m, CHAR_ANIM_PUT_CAP_ON); - if (animFrame == 0) { + if (animFrame == 0 && !m->area->camera->paletteEditorCap) { enable_time_stop_if_alone(); } @@ -1864,6 +1864,28 @@ s32 act_putting_on_cap(struct MarioState *m) { return FALSE; } +// coop custom action +s32 act_taking_off_cap(struct MarioState *m) { + s16 animFrame = set_character_animation(m, CHAR_ANIM_TAKE_CAP_OFF_THEN_ON); + switch (animFrame) { + case 0: + if (!m->area->camera->paletteEditorCap) { + enable_time_stop_if_alone(); + } + break; + case 12: + cutscene_take_cap_off(m); + break; + case 30: + set_mario_action(m, ACT_IDLE, 0); + disable_time_stop(); + break; + } + + stationary_ground_step(m); + return FALSE; +} + void stuck_in_ground_handler(struct MarioState *m, s32 animation, s32 unstuckFrame, s32 target2, s32 target3, s32 endAction) { if (!m) { return; } @@ -3124,6 +3146,7 @@ s32 mario_execute_cutscene_action(struct MarioState *m) { case ACT_BUTT_STUCK_IN_GROUND: cancel = act_butt_stuck_in_ground(m); break; case ACT_FEET_STUCK_IN_GROUND: cancel = act_feet_stuck_in_ground(m); break; case ACT_PUTTING_ON_CAP: cancel = act_putting_on_cap(m); break; + case ACT_TAKING_OFF_CAP: cancel = act_taking_off_cap(m); break; default: LOG_ERROR("Attempted to execute unimplemented action '%04X'", m->action); set_mario_action(m, ACT_IDLE, 0); diff --git a/src/game/mario_actions_stationary.c b/src/game/mario_actions_stationary.c index 0bc00d9a..c64f6523 100644 --- a/src/game/mario_actions_stationary.c +++ b/src/game/mario_actions_stationary.c @@ -132,11 +132,11 @@ s32 act_idle(struct MarioState *m) { if (m->area && ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SNOW)) { return set_mario_action(m, ACT_SHIVERING, 0); } else { - if (!gDjuiInMainMenu) { - return set_mario_action(m, ACT_START_SLEEPING, 0); - } else { + if (gDjuiInMainMenu || gInPlayerMenu) { m->actionState = 0; m->actionTimer = 0; + } else { + return set_mario_action(m, ACT_START_SLEEPING, 0); } } } @@ -274,7 +274,7 @@ s32 act_sleeping(struct MarioState *m) { if (!m) { return 0; } s32 animFrame; if (m->playerIndex == 0) { - if (m->input + if (m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED | INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE | INPUT_FIRST_PERSON | INPUT_UNKNOWN_10 | INPUT_B_PRESSED | INPUT_Z_PRESSED)) { return set_mario_action(m, ACT_WAKING_UP, m->actionState); diff --git a/src/pc/djui/djui_panel_player.c b/src/pc/djui/djui_panel_player.c index a2bbbfc3..226c62ca 100644 --- a/src/pc/djui/djui_panel_player.c +++ b/src/pc/djui/djui_panel_player.c @@ -20,6 +20,14 @@ static struct DjuiSelectionbox* sPalettePresetSelection; static struct DjuiInputbox* sHexColorTextBox; static struct DjuiSlider *sSliderR, *sSliderG, *sSliderB; +bool gDjuiPanelPlayerCreated = false; + +static void djui_panel_player_update_camera_cutscene(void) { + if (gMarioState->area && gMarioState->area->camera && gMarioState->area->camera->cutscene == 0) { + gMarioState->area->camera->cutscene = CUTSCENE_PALETTE_EDITOR; + } +} + static void djui_panel_player_edit_palette_update_hex_code_box(void) { char buf[7]; static const char digitToChar[] = "0123456789abcdef"; @@ -235,6 +243,7 @@ static void djui_panel_player_destroy(UNUSED struct DjuiBase* caller) { void djui_panel_player_create(struct DjuiBase* caller) { djui_panel_player_prevent_demo(NULL); + djui_panel_player_update_camera_cutscene(); gInPlayerMenu = true; struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(PLAYER, PLAYER_TITLE)); diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index d52b8444..b2f5914c 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -254,23 +254,24 @@ static struct LuaObjectField sBullyCollisionDataFields[LUA_BULLY_COLLISION_DATA_ { "velZ", LVT_F32, offsetof(struct BullyCollisionData, velZ), false, LOT_NONE }, }; -#define LUA_CAMERA_FIELD_COUNT 13 +#define LUA_CAMERA_FIELD_COUNT 14 static struct LuaObjectField sCameraFields[LUA_CAMERA_FIELD_COUNT] = { - { "areaCenX", LVT_F32, offsetof(struct Camera, areaCenX), false, LOT_NONE }, - { "areaCenY", LVT_F32, offsetof(struct Camera, areaCenY), false, LOT_NONE }, - { "areaCenZ", LVT_F32, offsetof(struct Camera, areaCenZ), false, LOT_NONE }, - { "cutscene", LVT_U8, offsetof(struct Camera, cutscene), false, LOT_NONE }, - { "defMode", LVT_U8, offsetof(struct Camera, defMode), false, LOT_NONE }, - { "doorStatus", LVT_U8, offsetof(struct Camera, doorStatus), false, LOT_NONE }, -// { "filler31", LOT_???, offsetof(struct Camera, filler31), false, LOT_??? }, <--- UNIMPLEMENTED -// { "filler3C", LOT_???, offsetof(struct Camera, filler3C), false, LOT_??? }, <--- UNIMPLEMENTED - { "focus", LVT_COBJECT, offsetof(struct Camera, focus), true, LOT_VEC3F }, - { "mode", LVT_U8, offsetof(struct Camera, mode), false, LOT_NONE }, - { "mtx", LVT_COBJECT, offsetof(struct Camera, mtx), true, LOT_MAT4 }, - { "nextYaw", LVT_S16, offsetof(struct Camera, nextYaw), false, LOT_NONE }, - { "pos", LVT_COBJECT, offsetof(struct Camera, pos), true, LOT_VEC3F }, - { "unusedVec1", LVT_COBJECT, offsetof(struct Camera, unusedVec1), true, LOT_VEC3F }, - { "yaw", LVT_S16, offsetof(struct Camera, yaw), false, LOT_NONE }, + { "areaCenX", LVT_F32, offsetof(struct Camera, areaCenX), false, LOT_NONE }, + { "areaCenY", LVT_F32, offsetof(struct Camera, areaCenY), false, LOT_NONE }, + { "areaCenZ", LVT_F32, offsetof(struct Camera, areaCenZ), false, LOT_NONE }, + { "cutscene", LVT_U8, offsetof(struct Camera, cutscene), false, LOT_NONE }, + { "defMode", LVT_U8, offsetof(struct Camera, defMode), false, LOT_NONE }, + { "doorStatus", LVT_U8, offsetof(struct Camera, doorStatus), false, LOT_NONE }, +// { "filler31", LOT_???, offsetof(struct Camera, filler31), false, LOT_??? }, <--- UNIMPLEMENTED +// { "filler3C", LOT_???, offsetof(struct Camera, filler3C), false, LOT_??? }, <--- UNIMPLEMENTED + { "focus", LVT_COBJECT, offsetof(struct Camera, focus), true, LOT_VEC3F }, + { "mode", LVT_U8, offsetof(struct Camera, mode), false, LOT_NONE }, + { "mtx", LVT_COBJECT, offsetof(struct Camera, mtx), true, LOT_MAT4 }, + { "nextYaw", LVT_S16, offsetof(struct Camera, nextYaw), false, LOT_NONE }, + { "paletteEditorCap", LVT_BOOL, offsetof(struct Camera, paletteEditorCap), false, LOT_NONE }, + { "pos", LVT_COBJECT, offsetof(struct Camera, pos), true, LOT_VEC3F }, + { "unusedVec1", LVT_COBJECT, offsetof(struct Camera, unusedVec1), true, LOT_VEC3F }, + { "yaw", LVT_S16, offsetof(struct Camera, yaw), false, LOT_NONE }, }; #define LUA_CAMERA_FOVSTATUS_FIELD_COUNT 8 diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 7781f292..2fd0b6c2 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1059,6 +1059,7 @@ char gSmluaConstants[] = "" "CUTSCENE_EXIT_WATERFALL = 179\n" "CUTSCENE_EXIT_FALL_WMOTR = 180\n" "CUTSCENE_ENTER_POOL = 181\n" +"CUTSCENE_PALETTE_EDITOR = 182\n" "CUTSCENE_STOP = 0x8000\n" "CUTSCENE_LOOP = 0x7FFF\n" "HAND_CAM_SHAKE_OFF = 0\n" @@ -3232,6 +3233,7 @@ char gSmluaConstants[] = "" "ACT_BUTT_STUCK_IN_GROUND = 0x0002033B\n" "ACT_FEET_STUCK_IN_GROUND = 0x0002033C\n" "ACT_PUTTING_ON_CAP = 0x0000133D\n" +"ACT_TAKING_OFF_CAP = 0x0000133E\n" "ACT_HOLDING_POLE = 0x08100340\n" "ACT_GRAB_POLE_SLOW = 0x00100341\n" "ACT_GRAB_POLE_FAST = 0x00100342\n"