diff --git a/src/g_build_ticcmd.cpp b/src/g_build_ticcmd.cpp index 9ee6263f2..5c2abee86 100644 --- a/src/g_build_ticcmd.cpp +++ b/src/g_build_ticcmd.cpp @@ -206,9 +206,17 @@ class TiccmdBuilder return true; } + void toggle_freecam_input() + { + if (M_MenuButtonPressed(forplayer(), MBT_C)) + { + P_ToggleDemoCamera(); + } + } + bool director_input() { - if (G_IsPartyLocal(displayplayers[forplayer()]) == true) + if (demo.freecam || G_IsPartyLocal(displayplayers[forplayer()]) == true) { return false; } @@ -239,6 +247,8 @@ class TiccmdBuilder } } + toggle_freecam_input(); + return true; } @@ -376,6 +386,11 @@ public: if (!typing_input() && !director_input()) { regular_input(); + + if (demo.freecam) + { + toggle_freecam_input(); + } } return; diff --git a/src/k_hud.c b/src/k_hud.c index 0d928db0c..73caf2d96 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -5192,12 +5192,15 @@ static void K_drawDirectorHUD(void) offs = 2; } + K_DrawDirectorButton(offs + 1, "Freecam", kp_button_c[0], 0); + if (p == -1 || !playeringame[p] || players[p].spectator == false) { return; } - K_DrawDirectorButton(offs + 1, "Director", kp_button_r, + // TODO: this is too close to the screen bottom + K_DrawDirectorButton(offs + 2, "Director", kp_button_r, (directorinfo.active ? V_YELLOWMAP : 0)); if (players[p].flashing) @@ -5643,6 +5646,11 @@ void K_drawKartHUD(void) if (stplyr->karthud[khud_trickcool]) K_drawTrickCool(); + if (freecam) + { + K_DrawDirectorButton(3, "Freecam", kp_button_c[0], 0); + } + if (modeattacking || freecam) // everything after here is MP and debug only return; diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c index fba7ec7ed..68b4859dc 100644 --- a/src/menus/transient/pause-replay.c +++ b/src/menus/transient/pause-replay.c @@ -236,16 +236,7 @@ void M_PlaybackToggleFreecam(INT32 choice) splitscreen = 0; R_ExecuteSetViewSize(); - if (!demo.freecam) // toggle on - { - demo.freecam = true; - democam.button_a_held = 2; - democam.reset_aiming = true; - } - else // toggle off - { - demo.freecam = false; - } + P_ToggleDemoCamera(); } void M_PlaybackQuit(INT32 choice) diff --git a/src/p_local.h b/src/p_local.h index 919c73dec..b4bd09c51 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -154,6 +154,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); void P_DemoCameraMovement(camera_t *cam); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); +void P_ToggleDemoCamera(void); boolean P_PlayerInPain(player_t *player); void P_ResetPlayer(player_t *player); diff --git a/src/p_mobj.c b/src/p_mobj.c index 47d20059b..ddcce4818 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11969,6 +11969,15 @@ void P_SpawnPlayer(INT32 playernum) { K_ToggleDirector(players[consoleplayer].spectator && pcount > 0); } + + // TODO: handle splitscreen + // Spectators can switch to freecam. This should be + // disabled when they enter the race, or when the level + // changes. + if (playernum == consoleplayer && !demo.playback) + { + demo.freecam = false; + } } void P_AfterPlayerSpawn(INT32 playernum) diff --git a/src/p_user.c b/src/p_user.c index 97b6aefde..caec26b99 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2976,7 +2976,7 @@ void P_DemoCameraMovement(camera_t *cam) } } - if (!(cmd->buttons & BT_ACCELERATE) && democam.button_a_held) + if (!(cmd->buttons & (BT_ACCELERATE | BT_DRIFT)) && democam.button_a_held) { democam.button_a_held--; } @@ -3002,7 +3002,7 @@ void P_DemoCameraMovement(camera_t *cam) // forward/back will have a slope. So, as long as democam // controls haven't been used to alter the vertical angle, // slowly reset it to flat. - if ((democam.reset_aiming && moving) || (cmd->buttons & BT_DRIFT)) + if ((democam.reset_aiming && moving) || ((cmd->buttons & BT_DRIFT) && !democam.button_a_held)) { INT32 aiming = cam->aiming; INT32 smooth = FixedMul(ANGLE_11hh / 4, FCOS(cam->aiming)); @@ -3043,6 +3043,20 @@ void P_DemoCameraMovement(camera_t *cam) cam->subsector = R_PointInSubsector(cam->x, cam->y); } +void P_ToggleDemoCamera(void) +{ + if (!demo.freecam) // toggle on + { + demo.freecam = true; + democam.button_a_held = 2; + democam.reset_aiming = true; + } + else // toggle off + { + demo.freecam = false; + } +} + void P_ResetCamera(player_t *player, camera_t *thiscam) { tic_t tries = 0;