Merge pull request 'Spectator freecam' (#35) from freecamspectate into blankart-dev

Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/35
This commit is contained in:
NepDisk 2025-04-02 21:54:50 +00:00
commit 889170823d
24 changed files with 372 additions and 344 deletions

View file

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

View file

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

View file

@ -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]);
}
}
@ -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)

View file

@ -2255,7 +2255,7 @@ static void Command_View_f(void)
return;
}
if (demo.freecam)
if (camera[viewnum-1].freecam)
return;
displayplayerp = &displayplayers[viewnum-1];

View file

@ -505,8 +505,6 @@ struct player_t
// See pflags_t, above.
pflags_t pflags;
UINT16 postimgflags;
// playing animation.
panim_t panim;

View file

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

View file

@ -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;
@ -3212,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);
@ -3990,13 +3988,13 @@ void G_StopDemo(void)
demo.timing = false;
singletics = false;
demo.freecam = false;
// reset democam shit too:
democam.cam = NULL;
democam.soundmobj = NULL;
democam.localangle = 0;
democam.localaiming = 0;
democam.keyboardlook = false;
{
UINT8 i;
for (i = 0; i < MAXSPLITSCREENPLAYERS; ++i)
{
camera[i].freecam = false;
}
}
if (gamestate == GS_INTERMISSION)
Y_EndIntermission(); // cleanup

View file

@ -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
@ -976,13 +975,10 @@ 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;
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 (!thiscam->freecam && (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.
@ -1588,7 +1581,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))
{

View file

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

View file

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

View file

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

View file

@ -4219,22 +4219,13 @@ void M_PlaybackToggleFreecam(INT32 choice)
splitscreen = 0;
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.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
P_ToggleDemoCamera(i);
}
}
void M_PlaybackQuit(INT32 choice)
{
(void)choice;

View file

@ -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,25 +130,29 @@ 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;
// postproccess effects
UINT8 postimgflags;
};
// 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
// 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 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];
@ -161,9 +167,10 @@ 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);

View file

@ -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);
UINT8 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
@ -10648,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]);
}
}
}

View file

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

View file

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

View file

@ -1139,6 +1139,15 @@ boolean P_IsDisplayPlayer(player_t *player)
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;
}
@ -2068,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)
@ -2130,7 +2103,6 @@ void P_MovePlayer(player_t *player)
if (player->spectator)
{
player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip...
P_SpectatorMovement(player);
return;
}
@ -2671,54 +2643,85 @@ 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;
struct demofreecam_s democam;
// 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;
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
G_BuildTiccmd(cmd, 1, UINT8_MAX);
cmd = D_LocalTiccmd(num);
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 (!cam->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)) && cam->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 (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.
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) && !cam->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)
@ -2727,31 +2730,43 @@ 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_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)
@ -2812,8 +2827,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;
@ -2822,12 +2835,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL)
return true;
if (demo.freecam)
{
P_DemoCameraMovement(thiscam);
return true;
}
if (thiscam == &camera[1]) // Camera 2
{
num = 1;
@ -2845,6 +2852,17 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
num = 0;
}
if (thiscam->freecam || player->spectator)
{
UINT8 camnum = G_PartyPosition(g_localplayers[num]);
P_DemoCameraMovement(thiscam, camnum);
P_CalcChasePostImg(player, thiscam);
return true;
}
if (paused || P_AutoPause())
return true;
mo = player->mo;
if (player->playerstate == PST_DEAD)
@ -3346,14 +3364,94 @@ 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;
mtag_t sectag = Tag_FGet(&sector->tags);
if (Tag_FindLineSpecial(13, sectag))
return true;
if (sector->ffloors)
{
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;
}
}
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;
UINT8 postimgtype = 0;
//INT32 *param;
fixed_t pviewheight;
size_t i;
fixed_t pviewheight = 0;
/*for (i = 0; i <= splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
param = &postimgparam[i];
break;
}
}*/
if (encoremode) // srb2kart
postimgtype |= POSTIMG_MIRROR;
if (player->mo->eflags & MFE_VERTICALFLIP)
postimgtype |= POSTIMG_FLIP;
#ifdef HWRENDER
if (rendermode == render_opengl && splitscreen)
{
thiscam->postimgflags = postimgtype;
return;
}
#endif
sector = player->mo->subsector->sector;
if (player->mo->eflags & MFE_VERTICALFLIP)
pviewheight = player->mo->z + player->mo->height - player->viewheight;
@ -3366,105 +3464,25 @@ static void P_CalcPostImg(player_t *player)
pviewheight = player->awayviewmobj->z + 20*FRACUNIT;
}
/*for (i = 0; i <= (unsigned)r_splitscreen; i++)
{
if (player == &players[displayplayers[i]])
{
param = &postimgparam[i];
break;
}
}*/
// see if we are in heat (no, not THAT kind of heat...)
for (i = 0; i < sector->tags.count; i++)
{
if (Tag_FindLineSpecial(13, sector->tags.tags[i]) != -1)
{
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;
}
}
// 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<<FRACBITS))
{
typeflag |= POSTIMG_MOTION;
postimgtype |= POSTIMG_MOTION;
*param = (player->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)
@ -4247,7 +4265,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
{

View file

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

View file

@ -89,6 +89,7 @@ mobj_t *r_viewmobj;
int r_splitscreen;
fixed_t rendertimefrac;
fixed_t rendertimefrac_unpaused;
fixed_t renderdeltatics;
boolean renderisnewtic;
@ -913,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)
if (!player->spectator && !camera[viewnum].freecam)
{
roll += player->tilt;
}
@ -1202,20 +1203,21 @@ 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;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
R_InterpolateView(rendertimefrac);
R_InterpolateView(rendertimefrac_unpaused);
}
static void R_SetupAimingFrame(int s)
@ -1253,8 +1255,12 @@ void R_SetupFrame(int s, boolean skybox)
R_SetViewContext(static_cast<viewcontext_e>(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))
{
@ -1280,7 +1286,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;
@ -1426,10 +1432,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;
}
@ -1448,7 +1452,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

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
@ -190,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;

View file

@ -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] && !camera[i].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;
@ -883,6 +873,9 @@ void S_UpdateSounds(void)
for (i = r_splitscreen; i >= 0; i--)
{
if (camera[i].freecam)
continue;
if (c->origin != listenmobj[i])
continue;

View file

@ -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))
if (!demo.title && !P_IsLocalPlayer(stplyr) && !camera[viewnum].freecam)
{
if (!r_splitscreen)
{

View file

@ -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)<<FF_TRANSSHIFT);
*
* for (y = yoffset; y < yoffset+viewheight; y++)
* {
* for (x = xoffset; x < xoffset+viewwidth; x++)
* {
* tmpscr[y*vid.width + x]
* = colormaps[*(transme + (srcscr [(y*vid.width)+x ] <<8) + (tmpscr[(y*vid.width)+x]))];
}
}
}*/
if (player->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)<<FF_TRANSSHIFT);
for (y = yoffset; y < yoffset+viewheight; y++)
{
for (x = xoffset; x < xoffset+viewwidth; x++)
tmpscr[y*vid.width + x] = colormaps[*(transme + (srcscr [(y*vid.width)+x ] <<8) + (tmpscr[(y*vid.width)+x]))];
}
}*/
if ((thiscam->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;

View file

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