Merge branch 'update-freecam' into 'master'

Replay Freecam Love, accessible during regular gameplay, spectate and pause game anywhere, probably other fixes

See merge request KartKrew/Kart!1399
This commit is contained in:
James R 2023-08-19 12:02:51 +00:00
commit 16d966d583
22 changed files with 257 additions and 299 deletions

View file

@ -561,6 +561,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];

View file

@ -615,7 +615,9 @@ 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);

View file

@ -886,11 +886,14 @@ void D_SRB2Loop(void)
{
rendertimefrac = FRACUNIT;
}
rendertimefrac_unpaused = g_time.timefrac;
}
else
{
renderdeltatics = realtics * FRACUNIT;
rendertimefrac = FRACUNIT;
rendertimefrac_unpaused = FRACUNIT;
}
if (interp || doDisplay)

View file

@ -3690,11 +3690,14 @@ static void Command_Pause(void)
CONS_Printf(M_GetText("You can't pause here.\n"));
return;
}
// TODO: this would make a great debug feature for release
#ifndef DEVELOP
else if (modeattacking) // in time attack, pausing restarts the map
{
//M_ModeAttackRetry(0); // directly call from m_menu;
return;
}
#endif
SendNetXCmd(XD_PAUSE, &buf, 2);
}
@ -3715,8 +3718,11 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
return;
}
// TODO: this would make a great debug feature for release
#ifndef DEVELOP
if (modeattacking && !demo.playback)
return;
#endif
paused = READUINT8(*cp);
dedicatedpause = READUINT8(*cp);

View file

@ -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,12 +247,14 @@ class TiccmdBuilder
}
}
toggle_freecam_input();
return true;
}
bool spectator_analog_input()
{
if (!player()->spectator && !objectplacing)
if (!player()->spectator && !objectplacing && !demo.freecam)
{
return false;
}
@ -261,7 +271,7 @@ class TiccmdBuilder
if (G_PlayerInputDown(forplayer(), gc_lookback, 0))
{
cmd->aiming -= joystickvector.yaxis;
cmd->aiming -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE;
}
else
{
@ -361,10 +371,28 @@ public:
explicit TiccmdBuilder(ticcmd_t* cmd_, INT32 realtics_, UINT8 ssplayer_) :
cmd(cmd_), realtics(realtics_), ssplayer(ssplayer_), viewnum(G_PartyPosition(g_localplayers[forplayer()]))
{
*cmd = {}; // blank ticcmd
if (demo.playback)
auto regular_input = [this]
{
analog_input();
common_button_input();
};
if (demo.playback || demo.freecam || player()->spectator)
{
// freecam is controllable even while paused
*cmd = {};
if (!typing_input() && !director_input())
{
regular_input();
if (demo.freecam)
{
toggle_freecam_input();
}
}
return;
}
@ -373,6 +401,8 @@ public:
return;
}
*cmd = {}; // blank ticcmd
if (gamestate == GS_LEVEL && player()->playerstate == PST_REBORN)
{
return;
@ -391,8 +421,7 @@ public:
if (!overlay)
{
analog_input();
common_button_input();
regular_input();
}
cmd->angle = localangle[viewnum] >> TICCMD_REDUCE;

View file

@ -4127,12 +4127,6 @@ void G_StopDemo(void)
singletics = false;
demo.freecam = false;
// reset democam shit too:
democam.cam = NULL;
democam.soundmobj = NULL;
democam.localangle = 0;
democam.localaiming = 0;
democam.keyboardlook = false;
Z_Free(demo.skinlist);
demo.skinlist = NULL;

View file

@ -76,6 +76,10 @@
#include "discord.h"
#endif
#ifdef HWRENDER
#include "hardware/hw_main.h" // for cv_glshearing
#endif
gameaction_t gameaction;
gamestate_t gamestate = GS_NULL;
UINT8 ultimatemode = false;
@ -861,7 +865,7 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming)
INT32 limitangle;
// note: the current software mode implementation doesn't have true perspective
limitangle = ANGLE_90 - ANG10; // Some viewing fun, but not too far down...
limitangle = ANGLE_45; // Some viewing fun, but not too far down...
if (*aiming > limitangle)
*aiming = limitangle;
@ -871,6 +875,31 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming)
return (INT16)((*aiming)>>16);
}
void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox)
{
#ifndef HWRENDER
(void)player;
(void)skybox;
#endif
// clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...)
if (rendermode == render_soft
#ifdef HWRENDER
|| (rendermode == render_opengl
&& (cv_glshearing.value == 1
|| (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))))
#endif
)
{
G_SoftwareClipAimingPitch(aiming);
}
else
{
G_ClipAimingPitch(aiming);
}
}
static INT32 G_GetValueFromControlTable(INT32 deviceID, INT32 deadzone, INT32 *controltable)
{
INT32 i, failret = NO_BINDS_REACHABLE;
@ -3289,6 +3318,10 @@ boolean G_GametypeHasTeams(void)
//
boolean G_GametypeHasSpectators(void)
{
// TODO: this would make a great debug feature for release
#ifdef DEVELOP
return true;
#endif
return (netgame || (multiplayer && demo.netgame));
}

View file

@ -126,6 +126,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n);
// clip the console player aiming to the view
INT32 G_ClipAimingPitch(INT32 *aiming);
INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox);
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed

View file

@ -127,7 +127,10 @@ void K_CheckBumpers(void)
{
if (nobumpers > 0 && nobumpers >= numingame)
{
// TODO: this would make a great debug feature for release
#ifndef DEVELOP
P_DoAllPlayersExit(PF_NOCONTEST, false);
#endif
return;
}
}

View file

@ -5169,7 +5169,8 @@ static void K_DrawDirectorButton(INT32 idx, const char *label, patch_t *kp[2], I
static void K_drawDirectorHUD(void)
{
const INT32 p = G_PartyMember(consoleplayer, R_GetViewNumber());
const UINT8 viewnum = R_GetViewNumber();
const INT32 p = viewnum < G_PartySize(consoleplayer) ? G_PartyMember(consoleplayer, viewnum) : -1;
const char *itemtxt = "Join";
UINT8 offs = 0;
@ -5192,12 +5193,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 +5647,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;
@ -5659,7 +5668,7 @@ void K_drawKartHUD(void)
K_drawKartPowerUps();
if (G_IsPartyLocal(displayplayers[viewnum]) == false && !demo.playback)
if (G_IsPartyLocal(displayplayers[viewnum]) == false)
{
K_drawDirectorHUD();
}

View file

@ -236,20 +236,7 @@ void M_PlaybackToggleFreecam(INT32 choice)
splitscreen = 0;
R_ExecuteSetViewSize();
P_InitCameraCmd(); // init camera controls
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.turnheld = false;
democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway
}
P_ToggleDemoCamera();
}
void M_PlaybackQuit(INT32 choice)

View file

@ -1998,7 +1998,15 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
if (!player->exiting && (specialstageinfo.valid == true || modeattacking & ATTACKING_SPB))
{
// TODO: this would make a great debug feature for release
#ifdef DEVELOP
if (type != DMG_SPECTATOR)
{
P_DoPlayerExit(player, PF_NOCONTEST);
}
#else
P_DoPlayerExit(player, PF_NOCONTEST);
#endif
}
if (player->exiting)

View file

@ -126,6 +126,9 @@ struct camera_t
// SRB2Kart: camera pitches on slopes
angle_t pitch;
// Freecam: aiming needs to be reset after switching from chasecam
boolean reset_aiming;
// Interpolation data
fixed_t old_x, old_y, old_z;
angle_t old_angle, old_aiming;
@ -134,13 +137,7 @@ struct camera_t
// demo freecam or something before i commit die
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
boolean turnheld; // holding turn button for gradual turn speed
boolean keyboardlook; // keyboard look
UINT8 button_a_held; // A button was held since entering from menu, so don't move camera
};
extern struct demofreecam_s democam;
@ -159,7 +156,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_InitCameraCmd(void);
void P_ToggleDemoCamera(void);
boolean P_PlayerInPain(player_t *player);
void P_ResetPlayer(player_t *player);

View file

@ -11841,7 +11841,10 @@ void P_SpawnPlayer(INT32 playernum)
}
else // Otherwise, never spectator.
{
// TODO: this would make a great debug feature for release
#ifndef DEVELOP
p->spectator = false;
#endif
}
}
@ -11969,6 +11972,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)
@ -12002,12 +12014,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]);
}
}
}

View file

@ -7735,6 +7735,8 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam)
cam->subsector = R_PointInSubsector(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)

View file

@ -729,8 +729,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);
else
P_RunChaseCameras(); // special case: allow freecam to MOVE during pause!
return;
}

View file

@ -1082,6 +1082,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]])
@ -2350,45 +2359,6 @@ static void P_UpdatePlayerAngle(player_t *player)
}
}
//
// P_SpectatorMovement
//
// Control for spectators in multiplayer
//
static void P_SpectatorMovement(player_t *player)
{
ticcmd_t *cmd = &player->cmd;
P_UpdatePlayerAngle(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->flags & MF_NOCLIPHEIGHT))
{
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)
@ -2415,7 +2385,6 @@ void P_MovePlayer(player_t *player)
if (player->spectator)
{
player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip...
P_SpectatorMovement(player);
return;
}
@ -2970,184 +2939,87 @@ 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};
// Heavily simplified version of G_BuildTicCmd that only takes the local first player's control input and converts it to readable ticcmd_t
// we then throw that ticcmd garbage in the camera and make it move
// TODO: please just use the normal ticcmd function somehow
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)
{
memset(&cameracmd, 0, sizeof(ticcmd_t)); // initialize cmd
}
static ticcmd_t *P_CameraCmd(camera_t *cam)
{
/*
INT32 forward, axis; //i
// these ones used for multiple conditions
boolean turnleft, turnright, mouseaiming;
boolean invertmouse, lookaxis, usejoystick, kbl;
INT32 player_invert;
INT32 screen_invert;
*/
ticcmd_t *cmd = &cameracmd;
(void)cam;
if (!demo.playback)
return cmd; // empty cmd, no.
/*
kbl = democam.keyboardlook;
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
mouseaiming = true;
invertmouse = cv_invertmouse.value;
lookaxis = cv_lookaxis[0].value;
usejoystick = true;
turnright = PlayerInputDown(1, gc_turnright);
turnleft = PlayerInputDown(1, gc_turnleft);
axis = PlayerJoyAxis(1, AXISTURN);
if (encoremode)
{
turnright ^= turnleft; // swap these using three XORs
turnleft ^= turnright;
turnright ^= turnleft;
axis = -axis;
}
if (axis != 0)
{
turnright = turnright || (axis > 0);
turnleft = turnleft || (axis < 0);
}
forward = 0;
cmd->turning = 0;
// let movement keys cancel each other out
if (turnright && !(turnleft))
{
cmd->turning -= KART_FULLTURN;
}
else if (turnleft && !(turnright))
{
cmd->turning += KART_FULLTURN;
}
cmd->turning -= (mousex * 8) * (encoremode ? -1 : 1);
axis = PlayerJoyAxis(1, AXISMOVE);
if (PlayerInputDown(1, gc_a) || (usejoystick && axis > 0))
cmd->buttons |= BT_ACCELERATE;
axis = PlayerJoyAxis(1, AXISBRAKE);
if (PlayerInputDown(1, gc_brake) || (usejoystick && axis > 0))
cmd->buttons |= BT_BRAKE;
axis = PlayerJoyAxis(1, AXISAIM);
if (PlayerInputDown(1, gc_aimforward) || (usejoystick && axis < 0))
forward += MAXPLMOVE;
if (PlayerInputDown(1, gc_aimbackward) || (usejoystick && axis > 0))
forward -= MAXPLMOVE;
// fire with any button/key
axis = PlayerJoyAxis(1, AXISFIRE);
if (PlayerInputDown(1, gc_fire) || (usejoystick && axis > 0))
cmd->buttons |= BT_ATTACK;
// spectator aiming shit, ahhhh...
player_invert = invertmouse ? -1 : 1;
screen_invert = 1; // nope
// mouse look stuff (mouse look is not the same as mouse aim)
kbl = false;
// looking up/down
cmd->aiming += (mlooky<<19)*player_invert*screen_invert;
axis = PlayerJoyAxis(1, AXISLOOK);
// spring back if not using keyboard neither mouselookin'
if (!kbl && !lookaxis && !mouseaiming)
cmd->aiming = 0;
if (PlayerInputDown(1, gc_lookup) || (axis < 0))
{
cmd->aiming += KB_LOOKSPEED * screen_invert;
kbl = true;
}
else if (PlayerInputDown(1, gc_lookdown) || (axis > 0))
{
cmd->aiming -= KB_LOOKSPEED * screen_invert;
kbl = true;
}
if (PlayerInputDown(1, gc_centerview)) // No need to put a spectator limit on this one though :V
cmd->aiming = 0;
cmd->forwardmove += (SINT8)forward;
if (cmd->forwardmove > MAXPLMOVE)
cmd->forwardmove = MAXPLMOVE;
else if (cmd->forwardmove < -MAXPLMOVE)
cmd->forwardmove = -MAXPLMOVE;
if (cmd->turning > KART_FULLTURN)
cmd->turning = KART_FULLTURN;
else if (cmd->turning < -KART_FULLTURN)
cmd->turning = -KART_FULLTURN;
democam.keyboardlook = kbl;
*/
return cmd;
}
void P_DemoCameraMovement(camera_t *cam)
{
ticcmd_t *cmd;
angle_t thrustangle;
mobj_t *awayviewmobj_hack;
player_t *lastp;
// update democam stuff with what we got here:
democam.cam = cam;
democam.localangle = cam->angle;
democam.localaiming = cam->aiming;
boolean moving = false;
// first off we need to get button input
cmd = P_CameraCmd(cam);
cmd = D_LocalTiccmd(0);
if (cmd->aiming != 0)
{
cam->aiming += cmd->aiming << TICCMD_REDUCE;
cam->reset_aiming = false;
}
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)
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;
moving = true;
}
else if (cmd->buttons & BT_BRAKE)
{
cam->z -= 32*mapobjectscale;
moving = true;
}
}
if (!(cmd->buttons & (BT_ACCELERATE | BT_DRIFT)) && 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 (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);
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.
cam->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 ((cam->reset_aiming && moving) || ((cmd->buttons & BT_DRIFT) && !democam.button_a_held))
{
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;
cam->reset_aiming = false; // completely smoothed out
}
}
G_FinalClipAimingPitch((INT32 *)&cam->aiming, NULL, false);
cam->momx = cam->momy = cam->momz = 0;
if (cmd->forwardmove != 0)
@ -3156,25 +3028,35 @@ 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 (!cam->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.
// 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_PointInSubsector(cam->x, cam->y);
}
void P_ToggleDemoCamera(void)
{
if (!demo.freecam) // toggle on
{
demo.freecam = true;
democam.button_a_held = 2;
camera[0].reset_aiming = true;
}
else // toggle off
{
demo.freecam = false;
}
}
void P_ResetCamera(player_t *player, camera_t *thiscam)
{
tic_t tries = 0;
@ -3211,6 +3093,8 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
thiscam->radius = 20*FRACUNIT;
thiscam->height = 16*FRACUNIT;
thiscam->reset_aiming = true;
while (!P_MoveChaseCamera(player,thiscam,true) && ++tries < 2*TICRATE);
}
@ -3239,8 +3123,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;
@ -3249,12 +3131,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;
playerScale = FixedDiv(player->mo->scale, mapobjectscale);
scaleDiff = playerScale - FRACUNIT;

View file

@ -22,9 +22,6 @@
#include "r_state.h"
#include "z_zone.h"
#include "console.h" // con_startup_loadprogress
#ifdef HWRENDER
#include "hardware/hw_main.h" // for cv_glshearing
#endif
static CV_PossibleValue_t fpscap_cons_t[] = {
#ifdef DEVELOP
@ -117,23 +114,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
static void R_SetupFreelook(player_t *player, boolean skybox)
{
#ifndef HWRENDER
(void)player;
(void)skybox;
#endif
// clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...)
if (rendermode == render_soft
#ifdef HWRENDER
|| (rendermode == render_opengl
&& (cv_glshearing.value == 1
|| (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))))
#endif
)
{
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
}
G_FinalClipAimingPitch((INT32 *)&aimingangle, player, skybox);
centeryfrac = (viewheight/2)<<FRACBITS;

View file

@ -81,6 +81,7 @@ mobj_t *r_viewmobj;
int r_splitscreen;
fixed_t rendertimefrac;
fixed_t rendertimefrac_unpaused;
fixed_t renderdeltatics;
boolean renderisnewtic;
@ -978,7 +979,7 @@ angle_t R_ViewRollAngle(const player_t *player)
if (cv_tilting.value)
{
if (!player->spectator)
if (!player->spectator && !demo.freecam)
{
roll += player->tilt;
}
@ -1227,7 +1228,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)
@ -1265,8 +1266,12 @@ void R_SetupFrame(int s)
R_SetViewContext(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))
{
@ -1292,7 +1297,7 @@ void R_SetupFrame(int s)
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
else if (!player->spectator && chasecam)
else if (chasecam)
// use outside cam view
{
r_viewmobj = NULL;
@ -1430,10 +1435,8 @@ boolean R_ViewpointHasChasecam(player_t *player)
}
}
if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN)
if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || player->spectator)
chasecam = true; // force chasecam on
else if (player->spectator) // no spectator chasecam
chasecam = false; // force chasecam off
return chasecam;
}
@ -1446,7 +1449,7 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox)
if (player->awayview.tics || skybox)
return chasecam;
// use outside cam view
else if (!player->spectator && chasecam)
else if (chasecam)
return true;
// use the player's eyes view

View file

@ -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

View file

@ -540,11 +540,6 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
continue;
}
if (i == 0 && democam.soundmobj)
{
continue;
}
if (player->awayview.tics)
{
listenmobj[i] = player->awayview.mobj;
@ -554,7 +549,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;
}
@ -827,11 +822,6 @@ void S_UpdateSounds(void)
continue;
}
if (i == 0 && democam.soundmobj)
{
continue;
}
if (player->awayview.tics)
{
listenmobj[i] = player->awayview.mobj;
@ -898,12 +888,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)

View file

@ -1171,7 +1171,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)
{