From f72aa63f363554e76e8a4240e7e529b3e9f5201e Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 01:00:11 -0700 Subject: [PATCH 01/23] Interpolate view, even when paused Fixes slideshow movement with demo freecam while paused. Does not appear to jitter like texture scrollers do. --- src/d_main.cpp | 3 +++ src/r_main.cpp | 3 ++- src/r_main.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 0fc9f36f1..8133900b8 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -907,11 +907,14 @@ void D_SRB2Loop(void) { rendertimefrac = FRACUNIT; } + + rendertimefrac_unpaused = g_time.timefrac; } else { renderdeltatics = realtics * FRACUNIT; rendertimefrac = FRACUNIT; + rendertimefrac_unpaused = FRACUNIT; } if ((interp || doDisplay) && !frameskip) diff --git a/src/r_main.cpp b/src/r_main.cpp index 8adb6ab5e..867cc950d 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -89,6 +89,7 @@ mobj_t *r_viewmobj; int r_splitscreen; fixed_t rendertimefrac; +fixed_t rendertimefrac_unpaused; fixed_t renderdeltatics; boolean renderisnewtic; @@ -1215,7 +1216,7 @@ R_SetupCommonFrame else newview->sector = R_PointInSubsector(newview->x, newview->y)->sector; - R_InterpolateView(rendertimefrac); + R_InterpolateView(rendertimefrac_unpaused); } static void R_SetupAimingFrame(int s) diff --git a/src/r_main.h b/src/r_main.h index 762095bff..c3dd7a5b4 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -39,6 +39,8 @@ extern size_t validcount, linecount, loopcount, framecount; // The fraction of a tic being drawn (for interpolation between two tics) extern fixed_t rendertimefrac; +// Same as rendertimefrac but not suspended when the game is paused +extern fixed_t rendertimefrac_unpaused; // Evaluated delta tics for this frame (how many tics since the last frame) extern fixed_t renderdeltatics; // The current render is a new logical tic From 10e4fb183da4d331964d83ec6305375603de4b0f Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 01:15:45 -0700 Subject: [PATCH 02/23] ST_overlayDrawer: hide VIEWPOINT text when using demo freecam --- src/st_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 6a3756de9..74e6bfce7 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -743,7 +743,7 @@ static void ST_overlayDrawer(void) { if (cv_showviewpointtext.value) { - if (!demo.title && !P_IsLocalPlayer(stplyr)) + if (!demo.title && !P_IsLocalPlayer(stplyr) && !demo.freecam) { if (!r_splitscreen) { From 6531cc065ec929b6d12d0df01482c60bc1362463 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 01:16:35 -0700 Subject: [PATCH 03/23] Fix sound handling in demo freecam - Object sounds are audible from the location of the camera - Certain HUD sounds should no longer be audible - For instance, lap complete sfx --- src/g_demo.c | 1 - src/p_local.h | 1 - src/p_user.c | 20 +++++++++----------- src/s_sound.c | 23 ++++++++--------------- 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 52cfdf978..16c972c26 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3993,7 +3993,6 @@ void G_StopDemo(void) demo.freecam = false; // reset democam shit too: democam.cam = NULL; - democam.soundmobj = NULL; democam.localangle = 0; democam.localaiming = 0; democam.keyboardlook = false; diff --git a/src/p_local.h b/src/p_local.h index bfcccf4a4..fc5307be2 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -137,7 +137,6 @@ struct camera_t struct demofreecam_s { camera_t *cam; // this is useful when the game is paused, notably - mobj_t *soundmobj; // mobj to play sound from, used in s_sound angle_t localangle; // keeps track of the cam angle for cmds angle_t localaiming; // ditto with aiming diff --git a/src/p_user.c b/src/p_user.c index a50396c4e..c3a4ae9df 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1137,6 +1137,15 @@ boolean P_IsDisplayPlayer(player_t *player) return false; } + // Freecam still techically has a player in + // displayplayers. But since the camera is detached, it + // would be weird if sounds were heard from that player's + // perspective. + if (demo.freecam) + { + return false; + } + for (i = 0; i <= r_splitscreen; i++) // DON'T skip P1 { if (player == &players[displayplayers[i]]) @@ -2685,7 +2694,6 @@ void P_DemoCameraMovement(camera_t *cam) { ticcmd_t *cmd = &cameracmd;; angle_t thrustangle; - mobj_t *awayviewmobj_hack; player_t *lastp; // update democam stuff with what we got here: @@ -2734,14 +2742,6 @@ void P_DemoCameraMovement(camera_t *cam) // besides freecam going inside walls sounds pretty cool on paper. } - // awayviewmobj hack; this is to prevent us from hearing sounds from the player's perspective - - awayviewmobj_hack = P_SpawnMobj(cam->x, cam->y, cam->z, MT_THOK); - awayviewmobj_hack->tics = 2; - awayviewmobj_hack->renderflags |= RF_DONTDRAW; - - democam.soundmobj = awayviewmobj_hack; - // update subsector to avoid crashes; cam->subsector = R_PointInSubsectorFast(cam->x, cam->y); } @@ -2812,8 +2812,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->old_angle = thiscam->angle; thiscam->old_aiming = thiscam->aiming; - democam.soundmobj = NULL; // reset this each frame, we don't want the game crashing for stupid reasons now do we - // We probably shouldn't move the camera if there is no player or player mobj somehow if (!player || !player->mo) return true; diff --git a/src/s_sound.c b/src/s_sound.c index 3a6b606da..14b9ba89c 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -545,11 +545,6 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) continue; } - if (i == 0 && democam.soundmobj) - { - continue; - } - if (player->awayviewtics) { listenmobj[i] = player->awayviewmobj; @@ -559,7 +554,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) listenmobj[i] = player->mo; } - if (origin && origin == listenmobj[i]) + if (origin && origin == listenmobj[i] && !demo.freecam) { itsUs = true; } @@ -810,11 +805,6 @@ void S_UpdateSounds(void) continue; } - if (i == 0 && democam.soundmobj) - { - continue; - } - if (player->awayviewtics) { listenmobj[i] = player->awayviewmobj; @@ -881,12 +871,15 @@ void S_UpdateSounds(void) { boolean itsUs = false; - for (i = r_splitscreen; i >= 0; i--) + if (!demo.freecam) { - if (c->origin != listenmobj[i]) - continue; + for (i = r_splitscreen; i >= 0; i--) + { + if (c->origin != listenmobj[i]) + continue; - itsUs = true; + itsUs = true; + } } if (itsUs == false) From e0a191f4d59459b048ea04f84f83f06c229cd80b Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 01:50:34 -0700 Subject: [PATCH 04/23] Replace spectator movement with demo freecam --- src/g_demo.c | 5 ----- src/g_game.c | 4 ++-- src/m_menu.c | 4 ---- src/p_local.h | 13 ------------ src/p_tick.c | 5 ++--- src/p_user.c | 55 +++++--------------------------------------------- src/r_main.cpp | 16 ++++++++------- 7 files changed, 18 insertions(+), 84 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 16c972c26..be7d391ea 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3991,11 +3991,6 @@ void G_StopDemo(void) singletics = false; demo.freecam = false; - // reset democam shit too: - democam.cam = NULL; - democam.localangle = 0; - democam.localaiming = 0; - democam.keyboardlook = false; if (gamestate == GS_INTERMISSION) Y_EndIntermission(); // cleanup diff --git a/src/g_game.c b/src/g_game.c index 00857faaa..e3fe917e0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -976,8 +976,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) joystickvector2_t joystickvector; // you'd BETTER not touch the player while freecamming... - player_t *player = fordemocam ? NULL : &players[g_localplayers[forplayer]]; - camera_t *thiscam = fordemocam ? democam.cam : &camera[forplayer]; + player_t *player = &players[g_localplayers[forplayer]]; + camera_t *thiscam = &camera[forplayer]; boolean *rd = &resetdown[forplayer]; boolean spectating = fordemocam || player->spectator; diff --git a/src/m_menu.c b/src/m_menu.c index 64ae9e8d4..dd68f5db1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4223,14 +4223,10 @@ void M_PlaybackToggleFreecam(INT32 choice) if (!demo.freecam) // toggle on { demo.freecam = true; - democam.cam = &camera[0]; // this is rather useful } else // toggle off { demo.freecam = false; - // reset democam vars: - democam.cam = NULL; - democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway } } diff --git a/src/p_local.h b/src/p_local.h index fc5307be2..35c6eb6cd 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -133,19 +133,6 @@ struct camera_t angle_t old_angle, old_aiming; }; -// demo freecam or something before i commit die -struct demofreecam_s { - - camera_t *cam; // this is useful when the game is paused, notably - - angle_t localangle; // keeps track of the cam angle for cmds - angle_t localaiming; // ditto with aiming - boolean turnheld; // holding turn button for gradual turn speed - boolean keyboardlook; // keyboard look -}; - -extern struct demofreecam_s democam; - extern camera_t camera[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS], cv_cam_still[MAXSPLITSCREENPLAYERS], cv_cam_height[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_speed[MAXSPLITSCREENPLAYERS], cv_cam_rotate[MAXSPLITSCREENPLAYERS]; diff --git a/src/p_tick.c b/src/p_tick.c index 0fe6d8822..b19e02bee 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -690,9 +690,8 @@ void P_Ticker(boolean run) timeinmap = (timeinmap-1) & ~3; G_PreviewRewind(leveltime); } - else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause! - P_DemoCameraMovement(democam.cam); - S_SetStackAdjustmentStart(); + else + P_RunChaseCameras(); // special case: allow freecam to MOVE during pause! return; } diff --git a/src/p_user.c b/src/p_user.c index c3a4ae9df..bb954160c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2077,42 +2077,6 @@ static void P_UpdateBotAngle(player_t* player) player->mo->angle = player->angleturn; } -// -// P_SpectatorMovement -// -// Control for spectators in multiplayer -// -static void P_SpectatorMovement(player_t *player) -{ - ticcmd_t *cmd = &player->cmd; - - player->mo->angle = cmd->angle<<16; - P_UpdatePlayerAiming(player); - - ticruned++; - if (!(cmd->flags & TICCMD_RECEIVED)) - ticmiss++; - - if (cmd->buttons & BT_ACCELERATE) - player->mo->z += 32*mapobjectscale; - else if (cmd->buttons & BT_BRAKE) - player->mo->z -= 32*mapobjectscale; - - if (player->mo->z > player->mo->ceilingz - player->mo->height) - player->mo->z = player->mo->ceilingz - player->mo->height; - if (player->mo->z < player->mo->floorz) - player->mo->z = player->mo->floorz; - - player->mo->momx = player->mo->momy = player->mo->momz = 0; - if (cmd->forwardmove != 0) - { - P_Thrust(player->mo, player->mo->angle, cmd->forwardmove*mapobjectscale); - - // Quake-style flying spectators :D - player->mo->momz += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(player->aiming)); - } -} - // // P_MovePlayer void P_MovePlayer(player_t *player) @@ -2139,7 +2103,6 @@ void P_MovePlayer(player_t *player) if (player->spectator) { player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip... - P_SpectatorMovement(player); return; } @@ -2682,8 +2645,6 @@ fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; static ticcmd_t cameracmd; -struct demofreecam_s democam; - // called by m_menu to reinit cam input every time it's toggled void P_InitCameraCmd(void) { @@ -2696,22 +2657,13 @@ void P_DemoCameraMovement(camera_t *cam) angle_t thrustangle; player_t *lastp; - // update democam stuff with what we got here: - democam.cam = cam; - democam.localangle = cam->angle; - democam.localaiming = cam->aiming; - // first off we need to get button input G_BuildTiccmd(cmd, 1, UINT8_MAX); cam->aiming += cmd->aiming << TICCMD_REDUCE; cam->angle += cmd->turning << TICCMD_REDUCE; - democam.localangle += cmd->turning << TICCMD_REDUCE; - democam.localaiming += cmd->aiming << TICCMD_REDUCE; - cam->aiming = G_ClipAimingPitch((INT32 *)&cam->aiming); - democam.localaiming = G_ClipAimingPitch((INT32 *)&democam.localaiming); // camera movement: if (cmd->buttons & BT_ACCELERATE) @@ -2720,7 +2672,7 @@ void P_DemoCameraMovement(camera_t *cam) cam->z -= 32*mapobjectscale; // if you hold item, you will lock on to displayplayer. (The last player you were ""f12-ing"") - if (cmd->buttons & BT_ATTACK) + if (demo.freecam && cmd->buttons & BT_ATTACK) { lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot. cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); @@ -2820,12 +2772,15 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) return true; - if (demo.freecam) + if (demo.freecam || player->spectator) { P_DemoCameraMovement(thiscam); return true; } + if (paused || P_AutoPause()) + return true; + if (thiscam == &camera[1]) // Camera 2 { num = 1; diff --git a/src/r_main.cpp b/src/r_main.cpp index 867cc950d..25017fd02 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1254,8 +1254,12 @@ void R_SetupFrame(int s, boolean skybox) R_SetViewContext(static_cast(VIEWCONTEXT_PLAYER1 + s)); - if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off + if (player->spectator) + { + // Free flying spectator uses demo freecam. This + // requires chasecam to be enabled. + chasecam = true; + } if (chasecam && (thiscam && !thiscam->chase)) { @@ -1281,7 +1285,7 @@ void R_SetupFrame(int s, boolean skybox) R_SetupCommonFrame(player, r_viewmobj->subsector); } - else if (!player->spectator && chasecam) + else if (chasecam) // use outside cam view { r_viewmobj = NULL; @@ -1429,10 +1433,8 @@ boolean R_ViewpointHasChasecam(player_t *player) } } - if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode || player->spectator) chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off return chasecam; } @@ -1451,7 +1453,7 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox) if (player->awayviewtics || skybox) return chasecam; // use outside cam view - else if (!player->spectator && chasecam) + else if (chasecam) return true; // use the player's eyes view From c84d9f24fdc0a45db6ca9715ed11fe21a9a728b5 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 01:55:00 -0700 Subject: [PATCH 05/23] P_DemoCameraMovement: don't let A button press from menu carry over to rise camera --- src/m_menu.c | 1 + src/menus/transient/pause-replay.c | 261 +++++++++++++++++++++++++++++ src/p_local.h | 8 + src/p_user.c | 17 +- 4 files changed, 283 insertions(+), 4 deletions(-) create mode 100644 src/menus/transient/pause-replay.c diff --git a/src/m_menu.c b/src/m_menu.c index dd68f5db1..e023026ea 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4223,6 +4223,7 @@ void M_PlaybackToggleFreecam(INT32 choice) if (!demo.freecam) // toggle on { demo.freecam = true; + democam.button_a_held = 2; } else // toggle off { diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c new file mode 100644 index 000000000..46c0a6cfb --- /dev/null +++ b/src/menus/transient/pause-replay.c @@ -0,0 +1,261 @@ +/// \file menus/transient/pause-replay.c +/// \brief Replay popup menu + +#include "../../k_menu.h" +#include "../../s_sound.h" +#include "../../p_tick.h" // leveltime +#include "../../i_time.h" +#include "../../r_main.h" // R_ExecuteSetViewSize +#include "../../p_local.h" // P_InitCameraCmd +#include "../../d_main.h" // D_StartTitle + +static void M_PlaybackTick(void); + +menuitem_t PAUSE_PlaybackMenu[] = +{ + {IT_CALL | IT_STRING, "Hide Menu", NULL, "M_PHIDE", {.routine = M_SelectableClearMenus}, 0, 0}, + + {IT_CALL | IT_STRING, "Rewind", NULL, "M_PREW", {.routine = M_PlaybackRewind}, 20, 0}, + {IT_CALL | IT_STRING, "Pause", NULL, "M_PPAUSE", {.routine = M_PlaybackPause}, 36, 0}, + {IT_CALL | IT_STRING, "Fast-Forward", NULL, "M_PFFWD", {.routine = M_PlaybackFastForward}, 52, 0}, + {IT_CALL | IT_STRING, "Backup Frame", NULL, "M_PSTEPB", {.routine = M_PlaybackRewind}, 20, 0}, + {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", {.routine = M_PlaybackPause}, 36, 0}, + {IT_CALL | IT_STRING, "Advance Frame", NULL, "M_PFADV", {.routine = M_PlaybackAdvance}, 52, 0}, + + {IT_ARROWS | IT_STRING, "View Count", NULL, "M_PVIEWS", {.routine = M_PlaybackSetViews}, 72, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 88, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 2", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 104, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 3", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 120, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 4", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 136, 0}, + + {IT_CALL | IT_STRING, "Toggle Free Camera", NULL, "M_PVIEWS", {.routine = M_PlaybackToggleFreecam}, 156, 0}, + {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", {.routine = M_PlaybackQuit}, 172, 0}, +}; + +menu_t PAUSE_PlaybackMenuDef = { + sizeof (PAUSE_PlaybackMenu) / sizeof (menuitem_t), + NULL, + 0, + PAUSE_PlaybackMenu, + BASEVIDWIDTH/2 - 88, 2, + 0, 0, + MBF_UD_LR_FLIPPED, + NULL, + 0, 0, + M_DrawPlaybackMenu, + M_PlaybackTick, + NULL, + NULL, + NULL +}; + +void M_EndModeAttackRun(void) +{ + G_CheckDemoStatus(); // Cancel recording + + Command_ExitGame_f(); // Clear a bunch of state + + modeattacking = ATTACKING_NONE; // Kept until now because of Command_ExitGame_f + + if (demo.title == true) + { + D_StartTitle(); + } + else + { + D_ClearState(); + M_StartControlPanel(); + } +} + +// Replay Playback Menu + +tic_t playback_last_menu_interaction_leveltime = 0; + +static void M_PlaybackTick(void) +{ + INT16 i; + + if (leveltime - playback_last_menu_interaction_leveltime >= 6*TICRATE) + playback_last_menu_interaction_leveltime = leveltime - 6*TICRATE; + + // Toggle items + if (paused && !demo.rewinding) + { + PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_DISABLED; + PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING; + + if (itemOn >= playback_rewind && itemOn <= playback_fastforward) + itemOn += playback_backframe - playback_rewind; + } + else + { + PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING; + PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_DISABLED; + + if (itemOn >= playback_backframe && itemOn <= playback_advanceframe) + itemOn -= playback_backframe - playback_rewind; + } + + if (modeattacking) + { + for (i = playback_viewcount; i <= playback_view4; i++) + PAUSE_PlaybackMenu[i].status = IT_DISABLED; + + //PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 72; + //PAUSE_PlaybackMenu[playback_quit].mvar1 = 88; + PAUSE_PlaybackMenu[playback_quit].mvar1 = 72; + + //currentMenu->x = BASEVIDWIDTH/2 - 52; + currentMenu->x = BASEVIDWIDTH/2 - 44; + } + else + { + PAUSE_PlaybackMenu[playback_viewcount].status = IT_ARROWS|IT_STRING; + + for (i = 0; i <= r_splitscreen; i++) + PAUSE_PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; + for (i = r_splitscreen+1; i < 4; i++) + PAUSE_PlaybackMenu[playback_view1+i].status = IT_DISABLED; + + //PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 156; + //PAUSE_PlaybackMenu[playback_quit].mvar1 = 172; + PAUSE_PlaybackMenu[playback_quit].mvar1 = 156; + + //currentMenu->x = BASEVIDWIDTH/2 - 94; + currentMenu->x = BASEVIDWIDTH/2 - 88; + } +} + +void M_SetPlaybackMenuPointer(void) +{ + itemOn = playback_pause; +} + +void M_PlaybackRewind(INT32 choice) +{ + static tic_t lastconfirmtime; + + (void)choice; + + if (!demo.rewinding) + { + if (paused) + { + G_ConfirmRewind(leveltime-1); + paused = true; + S_PauseAudio(); + } + else + demo.rewinding = paused = true; + } + else if (lastconfirmtime + TICRATE/2 < I_GetTime()) + { + lastconfirmtime = I_GetTime(); + G_ConfirmRewind(leveltime); + } + + CV_SetValue(&cv_playbackspeed, 1); +} + +void M_PlaybackPause(INT32 choice) +{ + (void)choice; + + paused = !paused; + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = true; + S_PauseAudio(); + } + else if (paused) + S_PauseAudio(); + else + S_ResumeAudio(); + + CV_SetValue(&cv_playbackspeed, 1); +} + +void M_PlaybackFastForward(INT32 choice) +{ + (void)choice; + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = false; + S_ResumeAudio(); + } + CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); +} + +void M_PlaybackAdvance(INT32 choice) +{ + (void)choice; + + paused = false; + TryRunTics(1); + paused = true; +} + +void M_PlaybackSetViews(INT32 choice) +{ + if (choice > 0) + { + if (r_splitscreen < 3) + G_AdjustView(r_splitscreen + 2, 0, true); + } + else if (r_splitscreen) + { + if (choice == 0) + { + r_splitscreen--; + } + else + { + r_splitscreen = 0; + } + R_ExecuteSetViewSize(); + } +} + +void M_PlaybackAdjustView(INT32 choice) +{ + G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); +} + +// this one's rather tricky +void M_PlaybackToggleFreecam(INT32 choice) +{ + (void)choice; + M_ClearMenus(true); + + // remove splitscreen: + splitscreen = 0; + R_ExecuteSetViewSize(); + + if (!demo.freecam) // toggle on + { + demo.freecam = true; + democam.button_a_held = 2; + } + else // toggle off + { + demo.freecam = false; + } +} + +void M_PlaybackQuit(INT32 choice) +{ + (void)choice; + G_StopDemo(); + + if (modeattacking) + M_EndModeAttackRun(); + else if (restoreMenu) + M_StartControlPanel(); + else + D_StartTitle(); +} diff --git a/src/p_local.h b/src/p_local.h index 35c6eb6cd..1ebcecbff 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -133,6 +133,14 @@ struct camera_t angle_t old_angle, old_aiming; }; +// demo freecam or something before i commit die +struct demofreecam_s { + + UINT8 button_a_held; // A button was held since entering from menu, so don't move camera +}; + +extern struct demofreecam_s democam; + extern camera_t camera[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS], cv_cam_still[MAXSPLITSCREENPLAYERS], cv_cam_height[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_speed[MAXSPLITSCREENPLAYERS], cv_cam_rotate[MAXSPLITSCREENPLAYERS]; diff --git a/src/p_user.c b/src/p_user.c index bb954160c..3d6b81d5c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2644,6 +2644,7 @@ fixed_t t_cam_height[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; static ticcmd_t cameracmd; +struct demofreecam_s democam; // called by m_menu to reinit cam input every time it's toggled void P_InitCameraCmd(void) @@ -2666,10 +2667,18 @@ void P_DemoCameraMovement(camera_t *cam) cam->aiming = G_ClipAimingPitch((INT32 *)&cam->aiming); // camera movement: - if (cmd->buttons & BT_ACCELERATE) - cam->z += 32*mapobjectscale; - else if (cmd->buttons & BT_BRAKE) - cam->z -= 32*mapobjectscale; + if (!democam.button_a_held) + { + if (cmd->buttons & BT_ACCELERATE) + cam->z += 32*mapobjectscale; + else if (cmd->buttons & BT_BRAKE) + cam->z -= 32*mapobjectscale; + } + + if (!(cmd->buttons & BT_ACCELERATE) && democam.button_a_held) + { + democam.button_a_held--; + } // if you hold item, you will lock on to displayplayer. (The last player you were ""f12-ing"") if (demo.freecam && cmd->buttons & BT_ATTACK) From 872b31563d946e71180d0cb9ff9c4c26dafcf3ba Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 14 Aug 2023 01:58:47 -0700 Subject: [PATCH 06/23] P_DemoCameraMovement: even out vertical angle after toggling After turning on freecam, the vertical angle is tilted slightly downward (this is carried over from normal chasecam). Interpolate that angle back to normal while moving forward. This makes it so you don't need to manually adjust the vertical angle, since it would cause forward movement to send you into the ground. --- src/menus/transient/pause-replay.c | 1 + src/p_local.h | 1 + src/p_user.c | 55 +++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c index 46c0a6cfb..fba7ec7ed 100644 --- a/src/menus/transient/pause-replay.c +++ b/src/menus/transient/pause-replay.c @@ -240,6 +240,7 @@ void M_PlaybackToggleFreecam(INT32 choice) { demo.freecam = true; democam.button_a_held = 2; + democam.reset_aiming = true; } else // toggle off { diff --git a/src/p_local.h b/src/p_local.h index 1ebcecbff..35a024177 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -137,6 +137,7 @@ struct camera_t struct demofreecam_s { UINT8 button_a_held; // A button was held since entering from menu, so don't move camera + boolean reset_aiming; // camera aiming needs to be reset from chase camera }; extern struct demofreecam_s democam; diff --git a/src/p_user.c b/src/p_user.c index 3d6b81d5c..603b13c88 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2658,21 +2658,33 @@ void P_DemoCameraMovement(camera_t *cam) angle_t thrustangle; player_t *lastp; + boolean moving = false; + // first off we need to get button input G_BuildTiccmd(cmd, 1, UINT8_MAX); - cam->aiming += cmd->aiming << TICCMD_REDUCE; - cam->angle += cmd->turning << TICCMD_REDUCE; + if (cmd->aiming != 0) + { + cam->aiming += cmd->aiming << TICCMD_REDUCE; - cam->aiming = G_ClipAimingPitch((INT32 *)&cam->aiming); + democam.reset_aiming = false; + } + + cam->angle += cmd->turning << TICCMD_REDUCE; // camera movement: if (!democam.button_a_held) { if (cmd->buttons & BT_ACCELERATE) + { cam->z += 32*mapobjectscale; + moving = true; + } else if (cmd->buttons & BT_BRAKE) + { cam->z -= 32*mapobjectscale; + moving = true; + } } if (!(cmd->buttons & BT_ACCELERATE) && democam.button_a_held) @@ -2686,8 +2698,39 @@ void P_DemoCameraMovement(camera_t *cam) lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot. cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); cam->aiming = R_PointToAngle2(0, cam->z, R_PointToDist2(cam->x, cam->y, lastp->mo->x, lastp->mo->y), lastp->mo->z + lastp->mo->scale*128*P_MobjFlip(lastp->mo)); // This is still unholy. Aim a bit above their heads. + + democam.reset_aiming = false; } + if (cmd->forwardmove != 0) + { + moving = true; + } + + // After switching to democam, the vertical angle of + // chasecam is inherited. This is intentional because it + // creates a smooth transition. However, moving + // 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) + { + INT32 aiming = cam->aiming; + INT32 smooth = FixedMul(ANGLE_11hh / 4, FCOS(cam->aiming)); + + if (abs(smooth) < abs(aiming)) + { + cam->aiming -= smooth * intsign(aiming); + } + else + { + cam->aiming = 0; + democam.reset_aiming = false; // completely smoothed out + } + } + + G_FinalClipAimingPitch((INT32 *)&cam->aiming, NULL, false); + cam->momx = cam->momy = cam->momz = 0; if (cmd->forwardmove != 0) @@ -2696,7 +2739,11 @@ void P_DemoCameraMovement(camera_t *cam) cam->x += FixedMul(cmd->forwardmove*mapobjectscale, FINECOSINE(thrustangle)); cam->y += FixedMul(cmd->forwardmove*mapobjectscale, FINESINE(thrustangle)); - cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming)); + + if (!democam.reset_aiming) + { + cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming)); + } // momentums are useless here, directly add to the coordinates // this.......... doesn't actually check for floors and walls and whatnot but the function to do that is a pure mess so fuck that. From c4825fb7e7315bd601470670363936cc5c6b54bd Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 15 Aug 2023 01:15:56 -0700 Subject: [PATCH 07/23] R_ViewRollAngle: don't apply camera tilting while using freecam --- src/r_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.cpp b/src/r_main.cpp index 25017fd02..dc4799b49 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -920,7 +920,7 @@ angle_t R_ViewRollAngle(const player_t *player) if (cv_tilting.value) { - if (!player->spectator) + if (!player->spectator && !demo.freecam) { roll += player->tilt; } From 3bab18cb2147342309ed876944fa1f356080722a Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 3 Sep 2023 18:52:11 -0500 Subject: [PATCH 08/23] Invert freecam turning in encore Fixes KartKrew/Kart#652 --- src/p_user.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 603b13c88..aff600af7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2657,6 +2657,7 @@ void P_DemoCameraMovement(camera_t *cam) ticcmd_t *cmd = &cameracmd;; angle_t thrustangle; player_t *lastp; + angle_t turning; boolean moving = false; @@ -2670,7 +2671,12 @@ void P_DemoCameraMovement(camera_t *cam) democam.reset_aiming = false; } - cam->angle += cmd->turning << TICCMD_REDUCE; + turning = cmd->turning << TICCMD_REDUCE; + if (encoremode) + { + turning = -turning; + } + cam->angle += turning; // camera movement: if (!democam.button_a_held) From c63d5965337a5b6eb5b24b41bca37e477feeb564 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 30 Mar 2025 09:46:57 -0400 Subject: [PATCH 09/23] Remove unsued new menu file --- src/menus/transient/pause-replay.c | 262 ----------------------------- 1 file changed, 262 deletions(-) delete mode 100644 src/menus/transient/pause-replay.c diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c deleted file mode 100644 index fba7ec7ed..000000000 --- a/src/menus/transient/pause-replay.c +++ /dev/null @@ -1,262 +0,0 @@ -/// \file menus/transient/pause-replay.c -/// \brief Replay popup menu - -#include "../../k_menu.h" -#include "../../s_sound.h" -#include "../../p_tick.h" // leveltime -#include "../../i_time.h" -#include "../../r_main.h" // R_ExecuteSetViewSize -#include "../../p_local.h" // P_InitCameraCmd -#include "../../d_main.h" // D_StartTitle - -static void M_PlaybackTick(void); - -menuitem_t PAUSE_PlaybackMenu[] = -{ - {IT_CALL | IT_STRING, "Hide Menu", NULL, "M_PHIDE", {.routine = M_SelectableClearMenus}, 0, 0}, - - {IT_CALL | IT_STRING, "Rewind", NULL, "M_PREW", {.routine = M_PlaybackRewind}, 20, 0}, - {IT_CALL | IT_STRING, "Pause", NULL, "M_PPAUSE", {.routine = M_PlaybackPause}, 36, 0}, - {IT_CALL | IT_STRING, "Fast-Forward", NULL, "M_PFFWD", {.routine = M_PlaybackFastForward}, 52, 0}, - {IT_CALL | IT_STRING, "Backup Frame", NULL, "M_PSTEPB", {.routine = M_PlaybackRewind}, 20, 0}, - {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", {.routine = M_PlaybackPause}, 36, 0}, - {IT_CALL | IT_STRING, "Advance Frame", NULL, "M_PFADV", {.routine = M_PlaybackAdvance}, 52, 0}, - - {IT_ARROWS | IT_STRING, "View Count", NULL, "M_PVIEWS", {.routine = M_PlaybackSetViews}, 72, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 88, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 2", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 104, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 3", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 120, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 4", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 136, 0}, - - {IT_CALL | IT_STRING, "Toggle Free Camera", NULL, "M_PVIEWS", {.routine = M_PlaybackToggleFreecam}, 156, 0}, - {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", {.routine = M_PlaybackQuit}, 172, 0}, -}; - -menu_t PAUSE_PlaybackMenuDef = { - sizeof (PAUSE_PlaybackMenu) / sizeof (menuitem_t), - NULL, - 0, - PAUSE_PlaybackMenu, - BASEVIDWIDTH/2 - 88, 2, - 0, 0, - MBF_UD_LR_FLIPPED, - NULL, - 0, 0, - M_DrawPlaybackMenu, - M_PlaybackTick, - NULL, - NULL, - NULL -}; - -void M_EndModeAttackRun(void) -{ - G_CheckDemoStatus(); // Cancel recording - - Command_ExitGame_f(); // Clear a bunch of state - - modeattacking = ATTACKING_NONE; // Kept until now because of Command_ExitGame_f - - if (demo.title == true) - { - D_StartTitle(); - } - else - { - D_ClearState(); - M_StartControlPanel(); - } -} - -// Replay Playback Menu - -tic_t playback_last_menu_interaction_leveltime = 0; - -static void M_PlaybackTick(void) -{ - INT16 i; - - if (leveltime - playback_last_menu_interaction_leveltime >= 6*TICRATE) - playback_last_menu_interaction_leveltime = leveltime - 6*TICRATE; - - // Toggle items - if (paused && !demo.rewinding) - { - PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_DISABLED; - PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING; - - if (itemOn >= playback_rewind && itemOn <= playback_fastforward) - itemOn += playback_backframe - playback_rewind; - } - else - { - PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING; - PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_DISABLED; - - if (itemOn >= playback_backframe && itemOn <= playback_advanceframe) - itemOn -= playback_backframe - playback_rewind; - } - - if (modeattacking) - { - for (i = playback_viewcount; i <= playback_view4; i++) - PAUSE_PlaybackMenu[i].status = IT_DISABLED; - - //PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 72; - //PAUSE_PlaybackMenu[playback_quit].mvar1 = 88; - PAUSE_PlaybackMenu[playback_quit].mvar1 = 72; - - //currentMenu->x = BASEVIDWIDTH/2 - 52; - currentMenu->x = BASEVIDWIDTH/2 - 44; - } - else - { - PAUSE_PlaybackMenu[playback_viewcount].status = IT_ARROWS|IT_STRING; - - for (i = 0; i <= r_splitscreen; i++) - PAUSE_PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; - for (i = r_splitscreen+1; i < 4; i++) - PAUSE_PlaybackMenu[playback_view1+i].status = IT_DISABLED; - - //PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 156; - //PAUSE_PlaybackMenu[playback_quit].mvar1 = 172; - PAUSE_PlaybackMenu[playback_quit].mvar1 = 156; - - //currentMenu->x = BASEVIDWIDTH/2 - 94; - currentMenu->x = BASEVIDWIDTH/2 - 88; - } -} - -void M_SetPlaybackMenuPointer(void) -{ - itemOn = playback_pause; -} - -void M_PlaybackRewind(INT32 choice) -{ - static tic_t lastconfirmtime; - - (void)choice; - - if (!demo.rewinding) - { - if (paused) - { - G_ConfirmRewind(leveltime-1); - paused = true; - S_PauseAudio(); - } - else - demo.rewinding = paused = true; - } - else if (lastconfirmtime + TICRATE/2 < I_GetTime()) - { - lastconfirmtime = I_GetTime(); - G_ConfirmRewind(leveltime); - } - - CV_SetValue(&cv_playbackspeed, 1); -} - -void M_PlaybackPause(INT32 choice) -{ - (void)choice; - - paused = !paused; - - if (demo.rewinding) - { - G_ConfirmRewind(leveltime); - paused = true; - S_PauseAudio(); - } - else if (paused) - S_PauseAudio(); - else - S_ResumeAudio(); - - CV_SetValue(&cv_playbackspeed, 1); -} - -void M_PlaybackFastForward(INT32 choice) -{ - (void)choice; - - if (demo.rewinding) - { - G_ConfirmRewind(leveltime); - paused = false; - S_ResumeAudio(); - } - CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); -} - -void M_PlaybackAdvance(INT32 choice) -{ - (void)choice; - - paused = false; - TryRunTics(1); - paused = true; -} - -void M_PlaybackSetViews(INT32 choice) -{ - if (choice > 0) - { - if (r_splitscreen < 3) - G_AdjustView(r_splitscreen + 2, 0, true); - } - else if (r_splitscreen) - { - if (choice == 0) - { - r_splitscreen--; - } - else - { - r_splitscreen = 0; - } - R_ExecuteSetViewSize(); - } -} - -void M_PlaybackAdjustView(INT32 choice) -{ - G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); -} - -// this one's rather tricky -void M_PlaybackToggleFreecam(INT32 choice) -{ - (void)choice; - M_ClearMenus(true); - - // remove splitscreen: - 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; - } -} - -void M_PlaybackQuit(INT32 choice) -{ - (void)choice; - G_StopDemo(); - - if (modeattacking) - M_EndModeAttackRun(); - else if (restoreMenu) - M_StartControlPanel(); - else - D_StartTitle(); -} From 6b1de73341d75a0c45327897e86e5bc1469f736d Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 3 Jan 2025 18:18:20 +0100 Subject: [PATCH 10/23] move postimg flags to camera struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - also dont let water and heat be applied on top of each other since it does not look good (water postimg takes priority over heat) - also save a little time in opengl splitscreen since it does not support heat or wöter effects --- src/d_main.cpp | 2 +- src/d_player.h | 2 - src/hardware/hw_main.c | 32 ++++--- src/p_local.h | 3 + src/p_mobj.c | 37 +++++---- src/p_user.c | 184 +++++++++++++++++++++-------------------- src/v_video.c | 52 ++++++------ src/v_video.h | 2 +- 8 files changed, 165 insertions(+), 149 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 8133900b8..7cd38ae6c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -367,7 +367,7 @@ static void D_RenderLevel(void) { R_ApplyViewMorph(i); - V_DoPostProcessor(i, &players[displayplayers[i]], postimgparam[i]); + V_DoPostProcessor(i, postimgparam[i]); } } diff --git a/src/d_player.h b/src/d_player.h index f17621d82..9c337042b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -505,8 +505,6 @@ struct player_t // See pflags_t, above. pflags_t pflags; - UINT16 postimgflags; - // playing animation. panim_t panim; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 29e463ba7..1fad73460 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5657,6 +5657,8 @@ void HWR_BuildSkyDome(void) static void HWR_DrawSkyBackground(player_t *player) { + UINT8 viewnum = R_GetViewNumber(); + camera_t *thiscam = &camera[viewnum]; HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); if (cv_glskydome.value) @@ -5672,15 +5674,15 @@ static void HWR_DrawSkyBackground(player_t *player) dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); dometransform.flip = false; - if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimgflags & POSTIMG_FLIP) && !(thiscam->postimgflags & POSTIMG_MIRROR)) dometransform.flip = true; dometransform.mirror = false; - if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) + if ((thiscam->postimgflags & POSTIMG_MIRROR) && !(thiscam->postimgflags & POSTIMG_FLIP)) dometransform.mirror = true; dometransform.mirrorflip = false; - if ((player->postimgflags & POSTIMG_FLIP) && (player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimgflags & POSTIMG_FLIP) && (thiscam->postimgflags & POSTIMG_MIRROR)) dometransform.mirrorflip = true; dometransform.scalex = 1; @@ -5926,6 +5928,8 @@ static void HWR_ClearClipper(void) // ========================================================================== void HWR_RenderSkyboxView(player_t *player) { + UINT8 viewnum = R_GetViewNumber(); + camera_t *thiscam = &camera[viewnum]; const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd); { @@ -5968,15 +5972,15 @@ void HWR_RenderSkyboxView(player_t *player) gl_viewludcos = FIXED_TO_FLOAT(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); atransform.flip = false; - if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimgflags & POSTIMG_FLIP) && !(thiscam->postimgflags & POSTIMG_MIRROR)) atransform.flip = true; atransform.mirror = false; - if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) + if ((thiscam->postimgflags & POSTIMG_MIRROR) && !(thiscam->postimgflags & POSTIMG_FLIP)) atransform.mirror = true; atransform.mirrorflip = false; - if ((player->postimgflags & POSTIMG_FLIP) && (player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimgflags & POSTIMG_FLIP) && (thiscam->postimgflags & POSTIMG_MIRROR)) atransform.mirrorflip = true; atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) @@ -6075,6 +6079,8 @@ static void HWR_RollTransform(FTransform *tr, angle_t roll) void HWR_RenderPlayerView(void) { player_t * player = &players[displayplayers[viewssnum]]; + UINT8 viewnum = R_GetViewNumber(); + camera_t *thiscam = &camera[viewnum]; const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd); @@ -6153,15 +6159,15 @@ void HWR_RenderPlayerView(void) gl_viewludcos = FIXED_TO_FLOAT(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); atransform.flip = false; - if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimgflags & POSTIMG_FLIP) && !(thiscam->postimgflags & POSTIMG_MIRROR)) atransform.flip = true; atransform.mirror = false; - if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) + if ((thiscam->postimgflags & POSTIMG_MIRROR) && !(thiscam->postimgflags & POSTIMG_FLIP)) atransform.mirror = true; atransform.mirrorflip = false; - if ((player->postimgflags & POSTIMG_FLIP) && (player->postimgflags & POSTIMG_MIRROR)) + if ((thiscam->postimgflags & POSTIMG_FLIP) && (thiscam->postimgflags & POSTIMG_MIRROR)) atransform.mirrorflip = true; atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) @@ -6562,8 +6568,12 @@ void HWR_DoPostProcessor(player_t *player) if (r_splitscreen) // Not supported in splitscreen - someone want to add support? return; + //UINT8 viewnum = R_GetViewNumber(); // see above + //camera_t *thiscam = &camera[viewnum]; + camera_t *thiscam = &camera[0]; + // Drunken vision! WooOOooo~ - if (player->postimgflags & POSTIMG_WATER || player->postimgflags & POSTIMG_HEAT) + if (thiscam->postimgflags & POSTIMG_WATER || thiscam->postimgflags & POSTIMG_HEAT) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; @@ -6575,7 +6585,7 @@ void HWR_DoPostProcessor(player_t *player) INT32 FREQUENCY; // Modifies the wave. - if (player->postimgflags & POSTIMG_WATER) + if (thiscam->postimgflags & POSTIMG_WATER) { WAVELENGTH = 5; AMPLITUDE = 40; diff --git a/src/p_local.h b/src/p_local.h index 35a024177..0f985b571 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -131,6 +131,9 @@ struct camera_t // Interpolation data fixed_t old_x, old_y, old_z; angle_t old_angle, old_aiming; + + // postproccess effects + UINT16 postimgflags; }; // demo freecam or something before i commit die diff --git a/src/p_mobj.c b/src/p_mobj.c index 14323e573..6c2615f29 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3546,18 +3546,25 @@ void P_DestroyRobots(void) // the below is chasecam only, if you're curious. check out P_CalcPostImg in p_user.c for first person void P_CalcChasePostImg(player_t *player, camera_t *thiscam) { - boolean flipcam = (player->pflags & PF_FLIPCAM && player->mo->eflags & MFE_VERTICALFLIP); - UINT16 postimgflags = 0; - UINT8 i; + const boolean flipcam = (player->pflags & PF_FLIPCAM && player->mo->eflags & MFE_VERTICALFLIP); + UINT16 postimgtype = 0; // This can happen when joining if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) return; if (encoremode) - postimgflags |= POSTIMG_MIRROR; + postimgtype |= POSTIMG_MIRROR; if (flipcam) - postimgflags |= POSTIMG_FLIP; + postimgtype |= POSTIMG_FLIP; + +#ifdef HWRENDER + if (rendermode == render_opengl && splitscreen) + { + thiscam->postimgflags = postimgtype; + return; + } +#endif if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist { @@ -3572,26 +3579,20 @@ void P_CalcChasePostImg(player_t *player, camera_t *thiscam) // Are we in water? if (P_CameraCheckWater(&dummycam)) - postimgflags |= POSTIMG_WATER; - if (P_CameraCheckHeat(&dummycam)) - postimgflags |= POSTIMG_HEAT; + postimgtype |= POSTIMG_WATER; + else if (P_CameraCheckHeat(&dummycam)) + postimgtype |= POSTIMG_HEAT; } else { // Are we in water? if (P_CameraCheckWater(thiscam)) - postimgflags |= POSTIMG_WATER; - if (P_CameraCheckHeat(thiscam)) - postimgflags |= POSTIMG_HEAT; + postimgtype |= POSTIMG_WATER; + else if (P_CameraCheckHeat(thiscam)) + postimgtype |= POSTIMG_HEAT; } - for (i = 0; i <= splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - - players[displayplayers[i]].postimgflags = postimgflags; - } + thiscam->postimgflags = postimgtype; } // P_CameraThinker diff --git a/src/p_user.c b/src/p_user.c index aff600af7..152dee043 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2661,6 +2661,9 @@ void P_DemoCameraMovement(camera_t *cam) boolean moving = false; + if (encoremode) + cam->postimgflags |= POSTIMG_MIRROR; + // first off we need to get button input G_BuildTiccmd(cmd, 1, UINT8_MAX); @@ -3361,27 +3364,71 @@ boolean P_SpectatorJoinGame(player_t *player) return true; // no more player->mo, cannot continue. } -// the below is first person only, if you're curious. check out P_CalcChasePostImg in p_mobj.c for chasecam -static void P_CalcPostImg(player_t *player) +static boolean P_CameraCheckHeatFirstperson(player_t *player, sector_t *sector, fixed_t pviewheight) { - sector_t *sector = player->mo->subsector->sector; - INT16 typeflag = 0; - //INT32 *param; - fixed_t pviewheight; - size_t i; + mtag_t sectag = Tag_FGet(§or->tags); - if (player->mo->eflags & MFE_VERTICALFLIP) - pviewheight = player->mo->z + player->mo->height - player->viewheight; - else - pviewheight = player->mo->z + player->viewheight; + if (Tag_FindLineSpecial(13, sectag)) + return true; - if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) + if (sector->ffloors) { - sector = player->awayviewmobj->subsector->sector; - pviewheight = player->awayviewmobj->z + 20*FRACUNIT; + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->fofflags & FOF_EXISTS)) + continue; + + if (pviewheight >= P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y)) + continue; + + if (pviewheight <= P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y)) + continue; + + sectag = Tag_FGet(&rover->master->frontsector->tags); + + if (Tag_FindLineSpecial(13, sectag)) + return true; + } } - /*for (i = 0; i <= (unsigned)r_splitscreen; i++) + return false; +} + +static boolean P_CameraCheckWaterFirstperson(player_t *player, sector_t *sector, fixed_t pviewheight) +{ + if (sector->ffloors) + { + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->fofflags & FOF_EXISTS) || !(rover->fofflags & FOF_SWIMMABLE) || rover->fofflags & FOF_BLOCKPLAYER) + continue; + + if (pviewheight >= P_GetFFloorTopZAt(rover, player->mo->x, player->mo->y)) + continue; + + if (pviewheight <= P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y)) + continue; + + return true; + } + } + + return false; +} + +// the below is first person only, if you're curious. check out P_CalcChasePostImg in p_mobj.c for chasecam +static void P_CalcPostImg(player_t *player, camera_t *thiscam) +{ + sector_t *sector = NULL; + INT16 postimgtype = 0; + //INT32 *param; + fixed_t pviewheight = 0; + + /*for (i = 0; i <= splitscreen; i++) { if (player == &players[displayplayers[i]]) { @@ -3390,96 +3437,55 @@ static void P_CalcPostImg(player_t *player) } }*/ - // see if we are in heat (no, not THAT kind of heat...) - for (i = 0; i < sector->tags.count; i++) + if (encoremode) // srb2kart + postimgtype |= POSTIMG_MIRROR; + + if (player->mo->eflags & MFE_VERTICALFLIP) + postimgtype |= POSTIMG_FLIP; + +#ifdef HWRENDER + if (rendermode == render_opengl && splitscreen) { - if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1) + thiscam->postimgflags = postimgtype; + return; + } +#endif + + sector = player->mo->subsector->sector; + + if (sector->ffloors) + { + if (player->mo->eflags & MFE_VERTICALFLIP) + pviewheight = player->mo->z + player->mo->height - player->viewheight; + else + pviewheight = player->mo->z + player->viewheight; + + if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) { - typeflag |= POSTIMG_HEAT; - break; - } - else if (sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight; - fixed_t bottomheight; - boolean gotres = false; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - size_t j; - - if (!(rover->fofflags & FOF_EXISTS)) - continue; - - topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); - bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); - - if (pviewheight >= topheight || pviewheight <= bottomheight) - continue; - - for (j = 0; j < rover->master->frontsector->tags.count; j++) - { - if (Tag_FindLineSpecial(13, rover->master->frontsector->tags.tags[j]) != -1) - { - typeflag |= POSTIMG_HEAT; - gotres = true; - break; - } - } - } - if (gotres) - break; + sector = player->awayviewmobj->subsector->sector; + pviewheight = player->awayviewmobj->z + 20*FRACUNIT; } } // see if we are in water (water trumps heat) - if (sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight; - fixed_t bottomheight; - - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!(rover->fofflags & FOF_EXISTS) || !(rover->fofflags & FOF_SWIMMABLE) || rover->fofflags & FOF_BLOCKPLAYER) - continue; - - topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); - bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); - - if (pviewheight >= topheight || pviewheight <= bottomheight) - continue; - - typeflag |= POSTIMG_WATER; - } - } - - if (encoremode) // srb2kart - typeflag |= POSTIMG_MIRROR; - - if (player->mo->eflags & MFE_VERTICALFLIP) - typeflag |= POSTIMG_FLIP; + if (P_CameraCheckWaterFirstperson(player, sector, pviewheight)) + postimgtype |= POSTIMG_WATER; + // see if we are in heat (no, not THAT kind of heat...) + else if (P_CameraCheckHeatFirstperson(player, sector, pviewheight)) + postimgtype |= POSTIMG_HEAT; // Motion blur // unused /*if (player->speed > (35<speed - 32)/4; if (*param > 5) *param = 5; }*/ - for (i = 0; i <= (unsigned)r_splitscreen; i++) - { - if (player != &players[displayplayers[i]]) - continue; - - players[displayplayers[i]].postimgflags = typeflag; - break; - } + thiscam->postimgflags = postimgtype; } void P_DoTimeOver(player_t *player) @@ -4262,7 +4268,7 @@ void P_PlayerAfterThink(player_t *player) if (!thiscam->chase) // bob view only if looking through the player's eyes { P_CalcHeight(player); - P_CalcPostImg(player); + P_CalcPostImg(player, thiscam); } else { diff --git a/src/v_video.c b/src/v_video.c index e41b10021..289d7eb70 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2840,7 +2840,7 @@ INT32 heatindex[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; // Perform a particular image postprocessing function. // -void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) +void V_DoPostProcessor(INT32 view, INT32 param) { #if NUMSCREENS < 5 // do not enable image post processing for ARM, SH and MIPS CPUs @@ -2859,6 +2859,11 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) if (view < 0 || view > 3 || view > r_splitscreen) return; + camera_t *thiscam = &camera[view]; + + if (!thiscam->postimgflags) + return; + if ((view == 1 && r_splitscreen == 1) || view >= 2) yoffset = viewheight; else @@ -2872,10 +2877,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) UINT8 *tmpscr = screens[4]; UINT8 *srcscr = screens[0]; - if (!player->postimgflags) - return; - - if (player->postimgflags & POSTIMG_WATER) + if (thiscam->postimgflags & POSTIMG_WATER) { INT32 y; // Set disStart to a range from 0 to FINEANGLE, incrementing by 128 per tic @@ -2933,25 +2935,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) tmpscr = srcscr; srcscr = tmp; } - - /*if (player->postimgflags & POSTIMG_MOTION) // Motion Blur! - * { - * INT32 x, y; - * - * // TODO: Add a postimg_param so that we can pick the translucency level... - * UINT8 *transme = transtables + ((param-1)<postimgflags & POSTIMG_HEAT) // Heat wave + else if (thiscam->postimgflags & POSTIMG_HEAT) // Heat wave { INT32 y; @@ -2998,7 +2982,21 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) srcscr = tmp; } - if ((player->postimgflags & POSTIMG_FLIP) && !(player->postimgflags & POSTIMG_MIRROR)) // Flip the screen upside-down + /*if (thiscam->postimg & POSTIMG_MOTION) // Motion Blur! + { + INT32 x, y; + + // TODO: Add a postimg_param so that we can pick the translucency level... + UINT8 *transme = transtables + ((param-1)<postimgflags & POSTIMG_FLIP) && !(thiscam->postimgflags & POSTIMG_MIRROR)) // Flip the screen upside-down { INT32 y, y2; @@ -3009,7 +3007,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) tmpscr = srcscr; srcscr = tmp; } - else if ((player->postimgflags & POSTIMG_MIRROR) && !(player->postimgflags & POSTIMG_FLIP)) // Flip the screen on the x axis + else if ((thiscam->postimgflags & POSTIMG_MIRROR) && !(thiscam->postimgflags & POSTIMG_FLIP)) // Flip the screen on the x axis { INT32 y, x, x2; @@ -3021,7 +3019,7 @@ void V_DoPostProcessor(INT32 view, player_t *player, INT32 param) tmpscr = srcscr; srcscr = tmp; } - else if ((player->postimgflags & POSTIMG_MIRROR) && (player->postimgflags & POSTIMG_FLIP)) // Flip the screen upside-down and on the x axis + else if ((thiscam->postimgflags & POSTIMG_MIRROR) && (thiscam->postimgflags & POSTIMG_FLIP)) // Flip the screen upside-down and on the x axis { INT32 y, x; diff --git a/src/v_video.h b/src/v_video.h index ad31c09cf..1a17cd84c 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -337,7 +337,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option); // Find string width from tny_font chars, 0.5x scale INT32 V_SmallThinStringWidth(const char *string, INT32 option); -void V_DoPostProcessor(INT32 view, player_t *player, INT32 param); +void V_DoPostProcessor(INT32 view, INT32 param); void V_DrawPatchFill(patch_t *pat); From 7656b519bfd80f433011355749037960f5f9c049 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 8 Jan 2025 18:23:25 +0100 Subject: [PATCH 11/23] fix postimg data types mismatch also remove the "postimgflag_t" typedef since its useless and use smoler type for everything we dont need much space lol --- src/doomtype.h | 9 --------- src/p_local.h | 12 +++++++++++- src/p_mobj.c | 2 +- src/p_user.c | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 1ebf0c27c..f74f340fe 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -340,15 +340,6 @@ union FColorRGBA } ATTRPACK; typedef union FColorRGBA RGBA_t; -typedef enum -{ - POSTIMG_WATER = 1, // Underwater screen effect. - POSTIMG_MOTION = 1<<1, // Unused motion blur effect. - POSTIMG_FLIP = 1<<2, // Flipcam screen effect. - POSTIMG_HEAT = 1<<3, // Heatwave screen effect. - POSTIMG_MIRROR = 1<<4, // encore screen effect. -} postimgflag_t; - typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num) #define LUMPERROR UINT32_MAX diff --git a/src/p_local.h b/src/p_local.h index 0f985b571..06d08f25a 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -133,7 +133,7 @@ struct camera_t angle_t old_angle, old_aiming; // postproccess effects - UINT16 postimgflags; + UINT8 postimgflags; }; // demo freecam or something before i commit die @@ -145,6 +145,16 @@ struct demofreecam_s { extern struct demofreecam_s democam; +// post process types +enum +{ + POSTIMG_WATER = 1, // Underwater screen effect. + POSTIMG_MOTION = 1<<1, // Unused motion blur effect. + POSTIMG_FLIP = 1<<2, // Flipcam screen effect. + POSTIMG_HEAT = 1<<3, // Heatwave screen effect. + POSTIMG_MIRROR = 1<<4, // encore screen effect. +}; + extern camera_t camera[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS], cv_cam_still[MAXSPLITSCREENPLAYERS], cv_cam_height[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_cam_speed[MAXSPLITSCREENPLAYERS], cv_cam_rotate[MAXSPLITSCREENPLAYERS]; diff --git a/src/p_mobj.c b/src/p_mobj.c index 6c2615f29..c50f2fb1b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3547,7 +3547,7 @@ void P_DestroyRobots(void) void P_CalcChasePostImg(player_t *player, camera_t *thiscam) { const boolean flipcam = (player->pflags & PF_FLIPCAM && player->mo->eflags & MFE_VERTICALFLIP); - UINT16 postimgtype = 0; + UINT8 postimgtype = 0; // This can happen when joining if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) diff --git a/src/p_user.c b/src/p_user.c index 152dee043..882059149 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3424,7 +3424,7 @@ static boolean P_CameraCheckWaterFirstperson(player_t *player, sector_t *sector, static void P_CalcPostImg(player_t *player, camera_t *thiscam) { sector_t *sector = NULL; - INT16 postimgtype = 0; + UINT8 postimgtype = 0; //INT32 *param; fixed_t pviewheight = 0; From 9587afa23b89bbe6fd159019de8b5039384de30b Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 6 Jan 2025 22:02:34 +0100 Subject: [PATCH 12/23] let postimg stuff also apply to freecam --- src/p_local.h | 1 + src/p_user.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/p_local.h b/src/p_local.h index 06d08f25a..e61057ef5 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -172,6 +172,7 @@ 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_InitCameraCmd(void); +void P_CalcChasePostImg(player_t *player, camera_t *thiscam); boolean P_CanPlayerTurn(player_t *player, ticcmd_t *cmd); diff --git a/src/p_user.c b/src/p_user.c index 882059149..bb45ed58b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2840,6 +2840,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (demo.freecam || player->spectator) { P_DemoCameraMovement(thiscam); + P_CalcChasePostImg(player, thiscam); return true; } From 8eced6db14720a0e7bb3c0d7fbe8b97542232954 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 3 Jan 2025 18:29:21 +0100 Subject: [PATCH 13/23] oops smol error --- src/p_user.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index bb45ed58b..ba1140534 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3454,18 +3454,15 @@ static void P_CalcPostImg(player_t *player, camera_t *thiscam) sector = player->mo->subsector->sector; - if (sector->ffloors) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - pviewheight = player->mo->z + player->mo->height - player->viewheight; - else - pviewheight = player->mo->z + player->viewheight; + if (player->mo->eflags & MFE_VERTICALFLIP) + pviewheight = player->mo->z + player->mo->height - player->viewheight; + else + pviewheight = player->mo->z + player->viewheight; - if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) - { - sector = player->awayviewmobj->subsector->sector; - pviewheight = player->awayviewmobj->z + 20*FRACUNIT; - } + if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) + { + sector = player->awayviewmobj->subsector->sector; + pviewheight = player->awayviewmobj->z + 20*FRACUNIT; } // see if we are in water (water trumps heat) From d6ed7e0373d84c73ccbaf3b2be1e248fa255b094 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 30 Mar 2025 11:05:50 -0400 Subject: [PATCH 14/23] No longer needed since it applies to freecam already --- src/p_user.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ba1140534..94aaf4b51 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2661,9 +2661,6 @@ void P_DemoCameraMovement(camera_t *cam) boolean moving = false; - if (encoremode) - cam->postimgflags |= POSTIMG_MIRROR; - // first off we need to get button input G_BuildTiccmd(cmd, 1, UINT8_MAX); From f3ecfae3d80a2d836e63d47a375d0ae55d1ae8a0 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 30 Mar 2025 11:06:44 -0400 Subject: [PATCH 15/23] Revert 'Invert freecam turning in encore' This reverts commit 3bab18cb2147342309ed876944fa1f356080722a. --- src/p_user.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 94aaf4b51..0a56b9bcf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2657,7 +2657,6 @@ void P_DemoCameraMovement(camera_t *cam) ticcmd_t *cmd = &cameracmd;; angle_t thrustangle; player_t *lastp; - angle_t turning; boolean moving = false; @@ -2671,12 +2670,7 @@ void P_DemoCameraMovement(camera_t *cam) democam.reset_aiming = false; } - turning = cmd->turning << TICCMD_REDUCE; - if (encoremode) - { - turning = -turning; - } - cam->angle += turning; + cam->angle += cmd->turning << TICCMD_REDUCE; // camera movement: if (!democam.button_a_held) From d22a1d062236296b1dc1cdc32b635498055f4fa1 Mon Sep 17 00:00:00 2001 From: "James R." Date: Sun, 1 Oct 2023 14:29:23 -0700 Subject: [PATCH 16/23] R_ResetViewInterpolation: wait an extra tic if R_UpdateViewInterpolation has not run yet, do not add extra time for subsequent calls --- src/r_fps.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/r_fps.c b/src/r_fps.c index 11f1b8378..ca2547121 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -23,6 +23,7 @@ #include "r_state.h" #include "z_zone.h" #include "console.h" // con_startup_loadprogress +#include "i_time.h" static CV_PossibleValue_t fpscap_cons_t[] = { #ifdef DEVELOP @@ -73,6 +74,7 @@ static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS]; static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS]; static viewvars_t *oldview = &pview_old[0]; +static tic_t last_view_update; static int oldview_invalid[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; viewvars_t *newview = &pview_new[0]; @@ -180,21 +182,27 @@ void R_UpdateViewInterpolation(void) skyview_old[i] = skyview_new[i]; if (oldview_invalid[i] > 0) oldview_invalid[i]--; } + + last_view_update = I_GetTime(); } void R_ResetViewInterpolation(UINT8 p) { + // Wait an extra tic if the interpolation state hasn't + // updated yet. + int t = last_view_update == I_GetTime() ? 1 : 2; + if (p == 0) { UINT8 i; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - oldview_invalid[i]++; + oldview_invalid[i] = t; } } else { - oldview_invalid[p - 1]++; + oldview_invalid[p - 1] = t; } } From 911afb22a686cb2999d3804324d4418de2fcfc5d Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 1 Apr 2025 13:57:27 -0400 Subject: [PATCH 17/23] Move freecam state to camera_t Based on https://git.do.srb2.org/KartKrew/RingRacers/-/commit/fa89576f34898d1ec0fb928292db0e0dafa8c0dc p1 still controls both cameras for now. --- src/d_netcmd.c | 2 +- src/g_demo.c | 11 ++++++---- src/g_game.c | 2 +- src/k_hud.c | 9 ++++---- src/k_kart.c | 8 +++---- src/m_menu.c | 11 +++------- src/p_local.h | 17 +++++++-------- src/p_user.c | 57 +++++++++++++++++++++++++++++++------------------- src/r_main.cpp | 7 ++++--- src/r_main.h | 2 +- src/s_sound.c | 16 +++++++------- src/st_stuff.c | 4 +++- 12 files changed, 81 insertions(+), 65 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c1d60fa5b..7d830ae48 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2255,7 +2255,7 @@ static void Command_View_f(void) return; } - if (demo.freecam) + if (camera[viewnum-1].freecam) return; displayplayerp = &displayplayers[viewnum-1]; diff --git a/src/g_demo.c b/src/g_demo.c index 3f8ab63c6..93e54cbad 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1709,9 +1709,6 @@ void G_ConfirmRewind(tic_t rewindtime) COM_BufInsertText("renderview on\n"); - if (demo.freecam) - return; // don't touch from there - splitscreen = oldss; displayplayers[0] = olddp1; displayplayers[1] = olddp2; @@ -3990,7 +3987,13 @@ void G_StopDemo(void) demo.timing = false; singletics = false; - demo.freecam = false; + { + UINT8 i; + for (i = 0; i < MAXSPLITSCREENPLAYERS; ++i) + { + camera[i].freecam = false; + } + } if (gamestate == GS_INTERMISSION) Y_EndIntermission(); // cleanup diff --git a/src/g_game.c b/src/g_game.c index e3fe917e0..67024a729 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1588,7 +1588,7 @@ boolean G_Responder(event_t *ev) } } - if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback && !demo.freecam) + if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback) { if (G_ControlBoundToKey(1, gc_viewpoint, ev->data1, false)) { diff --git a/src/k_hud.c b/src/k_hud.c index 3602bab6c..f5693c400 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2617,7 +2617,7 @@ static boolean K_ShowPlayerNametag(player_t *p) return false; } - if (demo.playback == true && demo.freecam == true) + if (demo.playback == true && camera[R_GetViewNumber()].freecam == true) { return true; } @@ -3046,7 +3046,7 @@ static void K_drawKartNameTags(void) if (result.onScreen == true) { - if (!(demo.playback == true && demo.freecam == true)) + if (!(demo.playback == true && camera[cnum].freecam == true)) { for (j = 0; j <= r_splitscreen; j++) { @@ -4493,7 +4493,8 @@ void K_drawKartHUD(void) { boolean islonesome = false; boolean battlefullscreen = false; - boolean freecam = demo.freecam; //disable some hud elements w/ freecam + UINT8 viewnum = R_GetViewNumber(); + boolean freecam = camera[viewnum].freecam; //disable some hud elements w/ freecam UINT8 i; // Define the X and Y for each drawn object @@ -4568,7 +4569,7 @@ void K_drawKartHUD(void) islonesome = K_drawKartPositionFaces(); } - if (!stplyr->spectator && !demo.freecam) // Bottom of the screen elements, don't need in spectate mode + if (!stplyr->spectator && !freecam) // Bottom of the screen elements, don't need in spectate mode { if (demo.title) // Draw title logo instead in demo.titles { diff --git a/src/k_kart.c b/src/k_kart.c index e4dfbcfdd..0f0d30d94 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1457,7 +1457,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) dontforcespb = true; // This makes the roulette produce the random noises. - if ((player->itemroulette % 3) == 1 && P_IsDisplayPlayer(player) && !demo.freecam) + if ((player->itemroulette % 3) == 1 && P_IsDisplayPlayer(player)) { #define PLAYROULETTESND S_StartSound(NULL, sfx_itrol1 + ((player->itemroulette / 3) % 8)) for (i = 0; i <= r_splitscreen; i++) @@ -1535,7 +1535,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) //player->itemblinkmode = 1; player->itemroulette = 0; player->roulettetype = 0; - if (P_IsDisplayPlayer(player) && !demo.freecam) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_itrole); return; } @@ -1550,7 +1550,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->itemblinkmode = 2; player->itemroulette = 0; player->roulettetype = 0; - if (P_IsDisplayPlayer(player) && !demo.freecam) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, sfx_dbgsal); return; } @@ -1712,7 +1712,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) player->itemamount = 1; } - if (P_IsDisplayPlayer(player) && !demo.freecam) + if (P_IsDisplayPlayer(player)) S_StartSound(NULL, ((player->roulettetype == 1) ? sfx_itrolk : (mashed ? sfx_itrolm : sfx_itrolf))); player->itemblink = TICRATE; diff --git a/src/m_menu.c b/src/m_menu.c index e023026ea..d5fe7d032 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4220,18 +4220,13 @@ void M_PlaybackToggleFreecam(INT32 choice) R_ExecuteSetViewSize(); P_InitCameraCmd(); // init camera controls - if (!demo.freecam) // toggle on + UINT8 i; + for (i = 0; i <= r_splitscreen; ++i) { - demo.freecam = true; - democam.button_a_held = 2; - } - else // toggle off - { - demo.freecam = false; + P_ToggleDemoCamera(i); } } - void M_PlaybackQuit(INT32 choice) { (void)choice; diff --git a/src/p_local.h b/src/p_local.h index e61057ef5..7598a7647 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -95,6 +95,8 @@ void P_UnlinkThinker(thinker_t *thinker); struct camera_t { boolean chase; + boolean freecam; + angle_t aiming; // Things used by FS cameras. @@ -128,6 +130,11 @@ struct camera_t // SRB2Kart: camera pitches on slopes angle_t pitch; + // Freecam: A button was held since entering from menu, so don't move camera + UINT8 button_a_held; + + boolean reset_aiming; // camera aiming needs to be reset from chase camera + // Interpolation data fixed_t old_x, old_y, old_z; angle_t old_angle, old_aiming; @@ -136,15 +143,6 @@ struct camera_t UINT8 postimgflags; }; -// demo freecam or something before i commit die -struct demofreecam_s { - - UINT8 button_a_held; // A button was held since entering from menu, so don't move camera - boolean reset_aiming; // camera aiming needs to be reset from chase camera -}; - -extern struct demofreecam_s democam; - // post process types enum { @@ -170,6 +168,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); void P_DemoCameraMovement(camera_t *cam); +void P_ToggleDemoCamera(UINT8 viewnum); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); void P_InitCameraCmd(void); void P_CalcChasePostImg(player_t *player, camera_t *thiscam); diff --git a/src/p_user.c b/src/p_user.c index 0a56b9bcf..4475b9c2c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1137,17 +1137,17 @@ boolean P_IsDisplayPlayer(player_t *player) return false; } - // Freecam still techically has a player in - // displayplayers. But since the camera is detached, it - // would be weird if sounds were heard from that player's - // perspective. - if (demo.freecam) - { - return false; - } - for (i = 0; i <= r_splitscreen; i++) // DON'T skip P1 { + if (camera[i].freecam) + { + // Freecam still techically has a player in + // displayplayers. But since the camera is + // detached, it would be weird if sounds were + // heard from that player's perspective. + continue; + } + if (player == &players[displayplayers[i]]) return true; } @@ -2644,7 +2644,6 @@ fixed_t t_cam_height[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; static ticcmd_t cameracmd; -struct demofreecam_s democam; // called by m_menu to reinit cam input every time it's toggled void P_InitCameraCmd(void) @@ -2667,13 +2666,13 @@ void P_DemoCameraMovement(camera_t *cam) { cam->aiming += cmd->aiming << TICCMD_REDUCE; - democam.reset_aiming = false; + cam->reset_aiming = false; } cam->angle += cmd->turning << TICCMD_REDUCE; // camera movement: - if (!democam.button_a_held) + if (!cam->button_a_held) { if (cmd->buttons & BT_ACCELERATE) { @@ -2687,19 +2686,19 @@ void P_DemoCameraMovement(camera_t *cam) } } - if (!(cmd->buttons & BT_ACCELERATE) && democam.button_a_held) + if (!(cmd->buttons & (BT_ACCELERATE | BT_DRIFT)) && cam->button_a_held) { - democam.button_a_held--; + cam->button_a_held--; } // if you hold item, you will lock on to displayplayer. (The last player you were ""f12-ing"") - if (demo.freecam && cmd->buttons & BT_ATTACK) + if (cam->freecam && cmd->buttons & BT_ATTACK) { lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot. cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y); cam->aiming = R_PointToAngle2(0, cam->z, R_PointToDist2(cam->x, cam->y, lastp->mo->x, lastp->mo->y), lastp->mo->z + lastp->mo->scale*128*P_MobjFlip(lastp->mo)); // This is still unholy. Aim a bit above their heads. - democam.reset_aiming = false; + cam->reset_aiming = false; } if (cmd->forwardmove != 0) @@ -2713,7 +2712,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) + if ((cam->reset_aiming && moving) || ((cmd->buttons & BT_DRIFT) && !cam->button_a_held)) { INT32 aiming = cam->aiming; INT32 smooth = FixedMul(ANGLE_11hh / 4, FCOS(cam->aiming)); @@ -2725,7 +2724,7 @@ void P_DemoCameraMovement(camera_t *cam) else { cam->aiming = 0; - democam.reset_aiming = false; // completely smoothed out + cam->reset_aiming = false; // completely smoothed out } } @@ -2740,7 +2739,7 @@ void P_DemoCameraMovement(camera_t *cam) cam->x += FixedMul(cmd->forwardmove*mapobjectscale, FINECOSINE(thrustangle)); cam->y += FixedMul(cmd->forwardmove*mapobjectscale, FINESINE(thrustangle)); - if (!democam.reset_aiming) + if (!cam->reset_aiming) { cam->z += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(cam->aiming)); } @@ -2754,12 +2753,28 @@ void P_DemoCameraMovement(camera_t *cam) cam->subsector = R_PointInSubsectorFast(cam->x, cam->y); } +void P_ToggleDemoCamera(UINT8 viewnum) +{ + camera_t *cam = &camera[viewnum]; + + if (!cam->freecam) // toggle on + { + cam->freecam = true; + cam->button_a_held = 2; + cam->reset_aiming = true; + } + else // toggle off + { + cam->freecam = false; + } +} + void P_ResetCamera(player_t *player, camera_t *thiscam) { tic_t tries = 0; fixed_t x, y, z; - if (demo.freecam) + if (thiscam->freecam) return; // do not reset the camera there. if (!player->mo) @@ -2828,7 +2843,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) return true; - if (demo.freecam || player->spectator) + if (thiscam->freecam || player->spectator) { P_DemoCameraMovement(thiscam); P_CalcChasePostImg(player, thiscam); diff --git a/src/r_main.cpp b/src/r_main.cpp index dc4799b49..678da36f6 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -914,13 +914,13 @@ void R_ApplyViewMorph(int s) width*vid.bpp, height, width*vid.bpp, vid.width); } -angle_t R_ViewRollAngle(const player_t *player) +angle_t R_ViewRollAngle(const player_t *player, UINT8 viewnum) { angle_t roll = player->viewrollangle; if (cv_tilting.value) { - if (!player->spectator && !demo.freecam) + if (!player->spectator && !camera[viewnum].freecam) { roll += player->tilt; } @@ -1203,13 +1203,14 @@ R_SetupCommonFrame ( player_t * player, subsector_t * subsector) { + const UINT8 viewnum = R_GetViewNumber(); newview->player = player; newview->x += quake.x; newview->y += quake.y; newview->z += quake.z; - newview->roll = R_ViewRollAngle(player); + newview->roll = R_ViewRollAngle(player, viewnum); if (subsector) newview->sector = subsector->sector; diff --git a/src/r_main.h b/src/r_main.h index c3dd7a5b4..cf4b02c0c 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -192,7 +192,7 @@ void R_Init(void); void R_CheckViewMorph(int split); void R_ApplyViewMorph(int split); -angle_t R_ViewRollAngle(const player_t *player); +angle_t R_ViewRollAngle(const player_t *player, UINT8 viewnum); // just sets setsizeneeded true extern boolean setsizeneeded; diff --git a/src/s_sound.c b/src/s_sound.c index 14b9ba89c..21369732a 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -554,7 +554,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) listenmobj[i] = player->mo; } - if (origin && origin == listenmobj[i] && !demo.freecam) + if (origin && origin == listenmobj[i] && !camera[i].freecam) { itsUs = true; } @@ -871,15 +871,15 @@ void S_UpdateSounds(void) { boolean itsUs = false; - if (!demo.freecam) + for (i = r_splitscreen; i >= 0; i--) { - for (i = r_splitscreen; i >= 0; i--) - { - if (c->origin != listenmobj[i]) - continue; + if (camera[i].freecam) + continue; - itsUs = true; - } + if (c->origin != listenmobj[i]) + continue; + + itsUs = true; } if (itsUs == false) diff --git a/src/st_stuff.c b/src/st_stuff.c index 74e6bfce7..2e404b3e8 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -726,6 +726,8 @@ void ST_preLevelTitleCardDrawer(void) // static void ST_overlayDrawer(void) { + const UINT8 viewnum = R_GetViewNumber(); + // hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) { @@ -743,7 +745,7 @@ static void ST_overlayDrawer(void) { if (cv_showviewpointtext.value) { - if (!demo.title && !P_IsLocalPlayer(stplyr) && !demo.freecam) + if (!demo.title && !P_IsLocalPlayer(stplyr) && !camera[viewnum].freecam) { if (!r_splitscreen) { From f81c76405732a96731713943482501ea722ce8df Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 1 Apr 2025 18:36:40 -0400 Subject: [PATCH 18/23] Fix Splitscreen freecam Based on https://git.srb2.org/KartKrew/RingRacers/-/commit/fec0f1341988f71e12462d64a41fd4361382a6b4 https://git.srb2.org/KartKrew/RingRacers/-/commit/0b7a6ed7f5cfadd122285188d7c7fd1104063028 --- src/d_clisrv.c | 5 +++++ src/d_clisrv.h | 1 + src/m_menu.c | 1 - src/p_local.h | 3 +-- src/p_user.c | 34 +++++++++++++--------------------- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 0666a7d80..5f7bb3c88 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -469,6 +469,11 @@ void D_ResetTiccmds(void) D_Clearticcmd(textcmds[i]->tic); } +ticcmd_t *D_LocalTiccmd(UINT8 ss) +{ + return &localcmds[ss][0]; +} + void SendKick(UINT8 playernum, UINT8 msg) { UINT8 buf[2]; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 6eb7bae29..bac2fac7d 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -512,6 +512,7 @@ extern UINT8 playerconsole[MAXPLAYERS]; INT32 D_NumPlayers(void); boolean D_IsPlayerHumanAndGaming(INT32 player_number); void D_ResetTiccmds(void); +ticcmd_t *D_LocalTiccmd(UINT8 ss); tic_t GetLag(INT32 node); UINT8 GetFreeXCmdSize(UINT8 playerid); diff --git a/src/m_menu.c b/src/m_menu.c index d5fe7d032..1c80d5318 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4219,7 +4219,6 @@ void M_PlaybackToggleFreecam(INT32 choice) splitscreen = 0; R_ExecuteSetViewSize(); - P_InitCameraCmd(); // init camera controls UINT8 i; for (i = 0; i <= r_splitscreen; ++i) { diff --git a/src/p_local.h b/src/p_local.h index 7598a7647..25c9c94c4 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -167,10 +167,9 @@ void P_AddPlayerScore(player_t *player, UINT32 amount); void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); -void P_DemoCameraMovement(camera_t *cam); +void P_DemoCameraMovement(camera_t *cam, UINT8 num); void P_ToggleDemoCamera(UINT8 viewnum); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); -void P_InitCameraCmd(void); void P_CalcChasePostImg(player_t *player, camera_t *thiscam); boolean P_CanPlayerTurn(player_t *player, ticcmd_t *cmd); diff --git a/src/p_user.c b/src/p_user.c index 4475b9c2c..c2a31d418 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2643,24 +2643,16 @@ fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; fixed_t t_cam_height[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; -static ticcmd_t cameracmd; - -// called by m_menu to reinit cam input every time it's toggled -void P_InitCameraCmd(void) +void P_DemoCameraMovement(camera_t *cam, UINT8 num) { - memset(&cameracmd, 0, sizeof(ticcmd_t)); // initialize cmd -} - -void P_DemoCameraMovement(camera_t *cam) -{ - ticcmd_t *cmd = &cameracmd;; + ticcmd_t *cmd; angle_t thrustangle; player_t *lastp; boolean moving = false; // first off we need to get button input - G_BuildTiccmd(cmd, 1, UINT8_MAX); + cmd = D_LocalTiccmd(num); if (cmd->aiming != 0) { @@ -2843,16 +2835,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) return true; - if (thiscam->freecam || player->spectator) - { - P_DemoCameraMovement(thiscam); - P_CalcChasePostImg(player, thiscam); - return true; - } - - if (paused || P_AutoPause()) - return true; - if (thiscam == &camera[1]) // Camera 2 { num = 1; @@ -2870,6 +2852,16 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall num = 0; } + if (thiscam->freecam || player->spectator) + { + P_DemoCameraMovement(thiscam, num); + P_CalcChasePostImg(player, thiscam); + return true; + } + + if (paused || P_AutoPause()) + return true; + mo = player->mo; if (player->playerstate == PST_DEAD) From 104bfaa7fe1d600b64ef1f31b7ddabc17f31b552 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 1 Apr 2025 20:30:09 -0400 Subject: [PATCH 19/23] Fix democam not moving --- src/g_game.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 67024a729..610409441 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -965,8 +965,7 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { - const boolean fordemocam = ssplayer == UINT8_MAX; - const UINT8 forplayer = fordemocam ? 0 : ssplayer-1; + const UINT8 forplayer = ssplayer-1; static INT32 turnheld[MAXSPLITSCREENPLAYERS]; // for accelerative turning static boolean resetdown[MAXSPLITSCREENPLAYERS]; // don't cam reset every frame @@ -979,10 +978,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) player_t *player = &players[g_localplayers[forplayer]]; camera_t *thiscam = &camera[forplayer]; boolean *rd = &resetdown[forplayer]; - boolean spectating = fordemocam || player->spectator; - - if (!fordemocam && demo.playback) return; - + boolean spectating = player->spectator || thiscam->freecam; // Is there any reason this can't just be I_BaseTiccmd? switch (ssplayer) { @@ -1003,12 +999,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. - if (!fordemocam && (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))) + if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN)) { return; } - if (!fordemocam && K_PlayerUsesBotMovement(player)) + if (K_PlayerUsesBotMovement(player)) { // Bot ticcmd is generated by K_BuildBotTiccmd return; @@ -1099,7 +1095,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) forward += (value * MAXPLMOVE) / JOYAXISRANGE; } - if (!fordemocam && player->sneakertimer) + if (player->sneakertimer) forward = MAXPLMOVE; // 50 value = G_PlayerInputAnalog(forplayer, gc_brake, false); @@ -1144,7 +1140,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->buttons |= BT_CUSTOM3; // Reset camera - if (!fordemocam && G_PlayerInputDown(forplayer, gc_camreset, false)) + if (G_PlayerInputDown(forplayer, gc_camreset, false)) { if (thiscam->chase && *rd == false) P_ResetCamera(player, thiscam); @@ -1156,7 +1152,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // spectator aiming shit, ahhhh... { INT32 screen_invert = - (!fordemocam && player->mo && (player->mo->eflags & MFE_VERTICALFLIP) + (player->mo && (player->mo->eflags & MFE_VERTICALFLIP) && (!thiscam->chase)) //because chasecam's not inverted ? -1 : 1; // set to -1 or 1 to multiply @@ -1197,7 +1193,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) -Making some galaxy brain autopilot Lua if you're a masochist -Making a Mario Kart 8 Deluxe tier baby mode that steers you away from walls and whatnot. You know what, do what you want! */ - if (!fordemocam && addedtogame && gamestate == GS_LEVEL) + if (addedtogame && gamestate == GS_LEVEL) { LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd)); @@ -1226,9 +1222,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else if (cmd->throwdir < -KART_FULLTURN) cmd->throwdir = -KART_FULLTURN; - if (fordemocam) - return; - G_DoAnglePrediction(cmd, realtics, ssplayer, player); // Reset away view if a command is given. From 79e81564c429f422b859ee6945abb4e2bc3b2bf5 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 1 Apr 2025 20:47:02 -0400 Subject: [PATCH 20/23] Freecam pause exception --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 610409441..4c54eb314 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -999,7 +999,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. - if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN)) + if (!thiscam->freecam && (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))) { return; } From 30cf74eb3e084ee4ce2c8214fc6b35d2be355fc3 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 8 Mar 2024 00:43:58 -0800 Subject: [PATCH 21/23] G_DoPlayDemo: clear camera_t - Fixes freecam not being reset between restarts --- src/g_demo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_demo.c b/src/g_demo.c index 93e54cbad..5a12d785e 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3209,6 +3209,7 @@ void G_DoPlayDemo(char *defdemoname) consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); memset(displayplayers,0,sizeof(displayplayers)); + memset(camera,0,sizeof(camera)); // reset freecam // Load players that were in-game when the map started p = READUINT8(demobuf.p); From 06c584d1fd364c26077c9aed8197639ffd1636e4 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 17 Aug 2023 17:38:24 -0700 Subject: [PATCH 22/23] Don't reset camera position when spectating Fixes a software renderer crash due to hitlag VFX from the player's death (death from spectating) being too close to the camera. --- src/p_mobj.c | 11 +++++++---- src/p_setup.c | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c50f2fb1b..607ed9a1b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10649,12 +10649,15 @@ void P_AfterPlayerSpawn(INT32 playernum) p->drawangle = mobj->angle; - for (i = 0; i <= r_splitscreen; i++) + if (p->spectator == false) { - if (camera[i].chase) + for (i = 0; i <= r_splitscreen; i++) { - if (displayplayers[i] == playernum) - P_ResetCamera(p, &camera[i]); + if (camera[i].chase) + { + if (displayplayers[i] == playernum) + P_ResetCamera(p, &camera[i]); + } } } diff --git a/src/p_setup.c b/src/p_setup.c index 9f3c0d0ea..6ebeac25f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8179,6 +8179,8 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam) cam->subsector = R_PointInSubsectorFast(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) } } + + cam->chase = false; // tell camera to reset its position next tic } static void P_InitCamera(void) From a0f5e41a2380e5edf6e2e6d772f9aa8bed547705 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 2 Apr 2025 16:57:35 -0400 Subject: [PATCH 23/23] Fix party system interaction with freecam --- src/p_user.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index c2a31d418..5da942c8b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2854,7 +2854,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->freecam || player->spectator) { - P_DemoCameraMovement(thiscam, num); + UINT8 camnum = G_PartyPosition(g_localplayers[num]); + P_DemoCameraMovement(thiscam, camnum); P_CalcChasePostImg(player, thiscam); return true; }