2010-02-15 23:26:55 +00:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
Copyright ( C ) 2002 - 2009 John Fitzgibbons and others
2014-09-22 08:55:46 +00:00
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
2010-02-15 23:26:55 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// view.c -- player eye positioning
# include "quakedef.h"
2017-09-17 02:12:53 +00:00
extern qboolean premul_hud ;
2010-02-15 23:26:55 +00:00
/*
The view is allowed to move slightly from it ' s true position for bobbing ,
but if it exceeds 8 pixels linear distance ( spherical , not box ) , the list of
entities sent from the server may not include everything in the pvs , especially
when crossing a water boudnary .
*/
2011-12-28 22:01:33 +00:00
cvar_t scr_ofsx = { " scr_ofsx " , " 0 " , CVAR_NONE } ;
cvar_t scr_ofsy = { " scr_ofsy " , " 0 " , CVAR_NONE } ;
cvar_t scr_ofsz = { " scr_ofsz " , " 0 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t cl_rollspeed = { " cl_rollspeed " , " 200 " , CVAR_NONE } ;
cvar_t cl_rollangle = { " cl_rollangle " , " 2.0 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t cl_bob = { " cl_bob " , " 0.02 " , CVAR_NONE } ;
cvar_t cl_bobcycle = { " cl_bobcycle " , " 0.6 " , CVAR_NONE } ;
cvar_t cl_bobup = { " cl_bobup " , " 0.5 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t v_kicktime = { " v_kicktime " , " 0.5 " , CVAR_NONE } ;
cvar_t v_kickroll = { " v_kickroll " , " 0.6 " , CVAR_NONE } ;
cvar_t v_kickpitch = { " v_kickpitch " , " 0.6 " , CVAR_NONE } ;
cvar_t v_gunkick = { " v_gunkick " , " 1 " , CVAR_NONE } ; //johnfitz
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t v_iyaw_cycle = { " v_iyaw_cycle " , " 2 " , CVAR_NONE } ;
cvar_t v_iroll_cycle = { " v_iroll_cycle " , " 0.5 " , CVAR_NONE } ;
cvar_t v_ipitch_cycle = { " v_ipitch_cycle " , " 1 " , CVAR_NONE } ;
cvar_t v_iyaw_level = { " v_iyaw_level " , " 0.3 " , CVAR_NONE } ;
cvar_t v_iroll_level = { " v_iroll_level " , " 0.1 " , CVAR_NONE } ;
cvar_t v_ipitch_level = { " v_ipitch_level " , " 0.3 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t v_idlescale = { " v_idlescale " , " 0 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t crosshair = { " crosshair " , " 0 " , CVAR_ARCHIVE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t gl_cshiftpercent = { " gl_cshiftpercent " , " 100 " , CVAR_NONE } ;
2017-10-03 19:49:04 +00:00
cvar_t gl_cshiftpercent_contents = { " gl_cshiftpercent_contents " , " 100 " , CVAR_NONE } ; // QuakeSpasm
cvar_t gl_cshiftpercent_damage = { " gl_cshiftpercent_damage " , " 100 " , CVAR_NONE } ; // QuakeSpasm
cvar_t gl_cshiftpercent_bonus = { " gl_cshiftpercent_bonus " , " 100 " , CVAR_NONE } ; // QuakeSpasm
cvar_t gl_cshiftpercent_powerup = { " gl_cshiftpercent_powerup " , " 100 " , CVAR_NONE } ; // QuakeSpasm
2010-02-15 23:26:55 +00:00
2017-08-19 01:35:54 +00:00
cvar_t r_viewmodel_quake = { " r_viewmodel_quake " , " 0 " , CVAR_ARCHIVE } ;
2010-02-15 23:26:55 +00:00
float v_dmg_time , v_dmg_roll , v_dmg_pitch ;
extern int in_forward , in_forward2 , in_back ;
vec3_t v_punchangles [ 2 ] ; //johnfitz -- copied from cl.punchangle. 0 is current, 1 is previous value. never the same unless map just loaded
2020-10-13 17:11:34 +00:00
double v_punchangles_times [ 2 ] ; //spike -- times, to avoid assumptions...
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = =
V_CalcRoll
Used by view and sv_user
= = = = = = = = = = = = = = =
*/
float V_CalcRoll ( vec3_t angles , vec3_t velocity )
{
2010-06-03 19:03:31 +00:00
vec3_t forward , right , up ;
2010-02-15 23:26:55 +00:00
float sign ;
float side ;
float value ;
AngleVectors ( angles , forward , right , up ) ;
side = DotProduct ( velocity , right ) ;
sign = side < 0 ? - 1 : 1 ;
side = fabs ( side ) ;
value = cl_rollangle . value ;
// if (cl.inwater)
// value *= 6;
if ( side < cl_rollspeed . value )
side = side * value / cl_rollspeed . value ;
else
side = value ;
return side * sign ;
}
/*
= = = = = = = = = = = = = = =
V_CalcBob
= = = = = = = = = = = = = = =
*/
float V_CalcBob ( void )
{
float bob ;
float cycle ;
2021-03-31 20:51:10 +00:00
if ( ! cl_bobcycle . value ) /* Avoid divide-by-zero, don't bob */
return 0.0f ;
2010-02-15 23:26:55 +00:00
cycle = cl . time - ( int ) ( cl . time / cl_bobcycle . value ) * cl_bobcycle . value ;
cycle / = cl_bobcycle . value ;
if ( cycle < cl_bobup . value )
cycle = M_PI * cycle / cl_bobup . value ;
else
cycle = M_PI + M_PI * ( cycle - cl_bobup . value ) / ( 1.0 - cl_bobup . value ) ;
// bob is proportional to velocity in the xy plane
// (don't count Z, or jumping messes it up)
bob = sqrt ( cl . velocity [ 0 ] * cl . velocity [ 0 ] + cl . velocity [ 1 ] * cl . velocity [ 1 ] ) * cl_bob . value ;
2010-08-01 19:22:46 +00:00
//Con_Printf ("speed: %5.1f\n", VectorLength(cl.velocity));
2010-02-15 23:26:55 +00:00
bob = bob * 0.3 + bob * 0.7 * sin ( cycle ) ;
if ( bob > 4 )
bob = 4 ;
else if ( bob < - 7 )
bob = - 7 ;
return bob ;
}
//=============================================================================
2011-12-28 22:01:33 +00:00
cvar_t v_centermove = { " v_centermove " , " 0.15 " , CVAR_NONE } ;
cvar_t v_centerspeed = { " v_centerspeed " , " 500 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
void V_StartPitchDrift ( void )
{
# if 1
if ( cl . laststop = = cl . time )
{
return ; // something else is keeping it from drifting
}
# endif
if ( cl . nodrift | | ! cl . pitchvel )
{
cl . pitchvel = v_centerspeed . value ;
cl . nodrift = false ;
cl . driftmove = 0 ;
}
}
void V_StopPitchDrift ( void )
{
cl . laststop = cl . time ;
cl . nodrift = true ;
cl . pitchvel = 0 ;
}
/*
= = = = = = = = = = = = = = =
V_DriftPitch
Moves the client pitch angle towards cl . idealpitch sent by the server .
If the user is adjusting pitch manually , either with lookup / lookdown ,
mlook and mouse , or klook and keyboard , pitch drifting is constantly stopped .
Drifting is enabled when the center view key is hit , mlook is released and
lookspring is non 0 , or when
= = = = = = = = = = = = = = =
*/
void V_DriftPitch ( void )
{
float delta , move ;
if ( noclip_anglehack | | ! cl . onground | | cls . demoplayback )
//FIXME: noclip_anglehack is set on the server, so in a nonlocal game this won't work.
{
cl . driftmove = 0 ;
cl . pitchvel = 0 ;
return ;
}
// don't count small mouse motion
if ( cl . nodrift )
{
2020-09-04 11:18:05 +00:00
if ( fabs ( cl . movecmds [ ( cl . movemessages - 1 ) & MOVECMDS_MASK ] . forwardmove ) < cl_forwardspeed . value )
2010-02-15 23:26:55 +00:00
cl . driftmove = 0 ;
else
cl . driftmove + = host_frametime ;
if ( cl . driftmove > v_centermove . value )
{
2011-08-25 21:37:34 +00:00
if ( lookspring . value )
V_StartPitchDrift ( ) ;
2010-02-15 23:26:55 +00:00
}
return ;
}
2017-09-17 02:12:53 +00:00
delta = cl . statsf [ STAT_IDEALPITCH ] - cl . viewangles [ PITCH ] ;
2010-02-15 23:26:55 +00:00
if ( ! delta )
{
cl . pitchvel = 0 ;
return ;
}
move = host_frametime * cl . pitchvel ;
cl . pitchvel + = host_frametime * v_centerspeed . value ;
//Con_Printf ("move: %f (%f)\n", move, host_frametime);
if ( delta > 0 )
{
if ( move > delta )
{
cl . pitchvel = 0 ;
move = delta ;
}
cl . viewangles [ PITCH ] + = move ;
}
else if ( delta < 0 )
{
if ( move > - delta )
{
cl . pitchvel = 0 ;
move = - delta ;
}
cl . viewangles [ PITCH ] - = move ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
VIEW BLENDING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
cshift_t cshift_empty = { { 130 , 80 , 50 } , 0 } ;
cshift_t cshift_water = { { 130 , 80 , 50 } , 128 } ;
cshift_t cshift_slime = { { 0 , 25 , 5 } , 150 } ;
cshift_t cshift_lava = { { 255 , 80 , 0 } , 150 } ;
float v_blend [ 4 ] ; // rgba 0.0 - 1.0
//johnfitz -- deleted BuildGammaTable(), V_CheckGamma(), gammatable[], and ramps[][]
/*
= = = = = = = = = = = = = = =
V_ParseDamage
= = = = = = = = = = = = = = =
*/
void V_ParseDamage ( void )
{
int armor , blood ;
vec3_t from ;
int i ;
vec3_t forward , right , up ;
entity_t * ent ;
float side ;
float count ;
armor = MSG_ReadByte ( ) ;
blood = MSG_ReadByte ( ) ;
for ( i = 0 ; i < 3 ; i + + )
2016-06-24 06:15:41 +00:00
from [ i ] = MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
2018-05-01 00:35:14 +00:00
if ( cl . qcvm . extfuncs . CSQC_Parse_Damage )
{
qboolean inhibit ;
PR_SwitchQCVM ( & cl . qcvm ) ;
pr_global_struct - > time = cl . time ;
G_FLOAT ( OFS_PARM0 ) = armor ;
G_FLOAT ( OFS_PARM1 ) = blood ;
G_VECTORSET ( OFS_PARM2 , from [ 0 ] , from [ 1 ] , from [ 2 ] ) ;
PR_ExecuteProgram ( cl . qcvm . extfuncs . CSQC_Parse_Damage ) ;
inhibit = G_FLOAT ( OFS_RETURN ) ;
PR_SwitchQCVM ( NULL ) ;
if ( inhibit )
return ;
}
2010-02-15 23:26:55 +00:00
count = blood * 0.5 + armor * 0.5 ;
if ( count < 10 )
count = 10 ;
cl . faceanimtime = cl . time + 0.2 ; // but sbar face into pain frame
cl . cshifts [ CSHIFT_DAMAGE ] . percent + = 3 * count ;
if ( cl . cshifts [ CSHIFT_DAMAGE ] . percent < 0 )
cl . cshifts [ CSHIFT_DAMAGE ] . percent = 0 ;
if ( cl . cshifts [ CSHIFT_DAMAGE ] . percent > 150 )
cl . cshifts [ CSHIFT_DAMAGE ] . percent = 150 ;
if ( armor > blood )
{
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 0 ] = 200 ;
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 1 ] = 100 ;
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 2 ] = 100 ;
}
else if ( armor )
{
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 0 ] = 220 ;
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 1 ] = 50 ;
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 2 ] = 50 ;
}
else
{
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 0 ] = 255 ;
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 1 ] = 0 ;
cl . cshifts [ CSHIFT_DAMAGE ] . destcolor [ 2 ] = 0 ;
}
//
// calculate view angle kicks
//
2017-09-17 02:12:53 +00:00
ent = & cl . entities [ cl . viewentity ] ;
2010-02-15 23:26:55 +00:00
VectorSubtract ( from , ent - > origin , from ) ;
VectorNormalize ( from ) ;
AngleVectors ( ent - > angles , forward , right , up ) ;
side = DotProduct ( from , right ) ;
v_dmg_roll = count * side * v_kickroll . value ;
side = DotProduct ( from , forward ) ;
v_dmg_pitch = count * side * v_kickpitch . value ;
v_dmg_time = v_kicktime . value ;
}
/*
= = = = = = = = = = = = = = = = = =
V_cshift_f
= = = = = = = = = = = = = = = = = =
*/
void V_cshift_f ( void )
{
cshift_empty . destcolor [ 0 ] = atoi ( Cmd_Argv ( 1 ) ) ;
cshift_empty . destcolor [ 1 ] = atoi ( Cmd_Argv ( 2 ) ) ;
cshift_empty . destcolor [ 2 ] = atoi ( Cmd_Argv ( 3 ) ) ;
cshift_empty . percent = atoi ( Cmd_Argv ( 4 ) ) ;
}
/*
= = = = = = = = = = = = = = = = = =
V_BonusFlash_f
When you run over an item , the server sends this command
= = = = = = = = = = = = = = = = = =
*/
void V_BonusFlash_f ( void )
{
2017-09-17 02:12:53 +00:00
if ( Cmd_Argc ( ) > = 5 )
{
cl . cshifts [ CSHIFT_BONUS ] . destcolor [ 0 ] = atof ( Cmd_Argv ( 1 ) ) * 255 ;
cl . cshifts [ CSHIFT_BONUS ] . destcolor [ 1 ] = atof ( Cmd_Argv ( 2 ) ) * 255 ;
cl . cshifts [ CSHIFT_BONUS ] . destcolor [ 2 ] = atof ( Cmd_Argv ( 3 ) ) * 255 ;
cl . cshifts [ CSHIFT_BONUS ] . percent = atof ( Cmd_Argv ( 4 ) ) * 255 ;
}
else
{
cl . cshifts [ CSHIFT_BONUS ] . destcolor [ 0 ] = 215 ;
cl . cshifts [ CSHIFT_BONUS ] . destcolor [ 1 ] = 186 ;
cl . cshifts [ CSHIFT_BONUS ] . destcolor [ 2 ] = 69 ;
cl . cshifts [ CSHIFT_BONUS ] . percent = 50 ;
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = =
V_SetContentsColor
Underwater , lava , etc each has a color shift
= = = = = = = = = = = = =
*/
void V_SetContentsColor ( int contents )
{
switch ( contents )
{
case CONTENTS_EMPTY :
case CONTENTS_SOLID :
case CONTENTS_SKY : //johnfitz -- no blend in sky
cl . cshifts [ CSHIFT_CONTENTS ] = cshift_empty ;
break ;
case CONTENTS_LAVA :
cl . cshifts [ CSHIFT_CONTENTS ] = cshift_lava ;
break ;
case CONTENTS_SLIME :
cl . cshifts [ CSHIFT_CONTENTS ] = cshift_slime ;
break ;
default :
cl . cshifts [ CSHIFT_CONTENTS ] = cshift_water ;
}
}
/*
= = = = = = = = = = = = =
V_CalcPowerupCshift
= = = = = = = = = = = = =
*/
void V_CalcPowerupCshift ( void )
{
if ( cl . items & IT_QUAD )
{
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 0 ] = 0 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 1 ] = 0 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 2 ] = 255 ;
cl . cshifts [ CSHIFT_POWERUP ] . percent = 30 ;
}
else if ( cl . items & IT_SUIT )
{
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 0 ] = 0 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 1 ] = 255 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 2 ] = 0 ;
cl . cshifts [ CSHIFT_POWERUP ] . percent = 20 ;
}
else if ( cl . items & IT_INVISIBILITY )
{
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 0 ] = 100 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 1 ] = 100 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 2 ] = 100 ;
cl . cshifts [ CSHIFT_POWERUP ] . percent = 100 ;
}
else if ( cl . items & IT_INVULNERABILITY )
{
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 0 ] = 255 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 1 ] = 255 ;
cl . cshifts [ CSHIFT_POWERUP ] . destcolor [ 2 ] = 0 ;
cl . cshifts [ CSHIFT_POWERUP ] . percent = 30 ;
}
else
cl . cshifts [ CSHIFT_POWERUP ] . percent = 0 ;
}
/*
= = = = = = = = = = = = =
V_CalcBlend
= = = = = = = = = = = = =
*/
void V_CalcBlend ( void )
{
float r , g , b , a , a2 ;
int j ;
2017-10-03 19:49:04 +00:00
cvar_t * cshiftpercent_cvars [ NUM_CSHIFTS ] = {
& gl_cshiftpercent_contents ,
& gl_cshiftpercent_damage ,
& gl_cshiftpercent_bonus ,
& gl_cshiftpercent_powerup
} ;
2010-02-15 23:26:55 +00:00
r = 0 ;
g = 0 ;
b = 0 ;
a = 0 ;
for ( j = 0 ; j < NUM_CSHIFTS ; j + + )
{
if ( ! gl_cshiftpercent . value )
continue ;
//johnfitz -- only apply leaf contents color shifts during intermission
if ( cl . intermission & & j ! = CSHIFT_CONTENTS )
continue ;
//johnfitz
a2 = ( ( cl . cshifts [ j ] . percent * gl_cshiftpercent . value ) / 100.0 ) / 255.0 ;
2017-10-03 19:49:04 +00:00
// QuakeSpasm -- also scale by the specific gl_cshiftpercent_* cvar
a2 * = ( cshiftpercent_cvars [ j ] - > value / 100.0 ) ;
// QuakeSpasm
2010-02-15 23:26:55 +00:00
if ( ! a2 )
continue ;
a = a + a2 * ( 1 - a ) ;
a2 = a2 / a ;
r = r * ( 1 - a2 ) + cl . cshifts [ j ] . destcolor [ 0 ] * a2 ;
g = g * ( 1 - a2 ) + cl . cshifts [ j ] . destcolor [ 1 ] * a2 ;
b = b * ( 1 - a2 ) + cl . cshifts [ j ] . destcolor [ 2 ] * a2 ;
}
v_blend [ 0 ] = r / 255.0 ;
v_blend [ 1 ] = g / 255.0 ;
v_blend [ 2 ] = b / 255.0 ;
v_blend [ 3 ] = a ;
if ( v_blend [ 3 ] > 1 )
v_blend [ 3 ] = 1 ;
if ( v_blend [ 3 ] < 0 )
v_blend [ 3 ] = 0 ;
}
/*
= = = = = = = = = = = = =
V_UpdateBlend - - johnfitz - - V_UpdatePalette cleaned up and renamed
= = = = = = = = = = = = =
*/
void V_UpdateBlend ( void )
{
int i , j ;
qboolean blend_changed ;
V_CalcPowerupCshift ( ) ;
blend_changed = false ;
for ( i = 0 ; i < NUM_CSHIFTS ; i + + )
{
if ( cl . cshifts [ i ] . percent ! = cl . prev_cshifts [ i ] . percent )
{
blend_changed = true ;
cl . prev_cshifts [ i ] . percent = cl . cshifts [ i ] . percent ;
}
for ( j = 0 ; j < 3 ; j + + )
if ( cl . cshifts [ i ] . destcolor [ j ] ! = cl . prev_cshifts [ i ] . destcolor [ j ] )
{
blend_changed = true ;
cl . prev_cshifts [ i ] . destcolor [ j ] = cl . cshifts [ i ] . destcolor [ j ] ;
}
}
// drop the damage value
cl . cshifts [ CSHIFT_DAMAGE ] . percent - = host_frametime * 150 ;
if ( cl . cshifts [ CSHIFT_DAMAGE ] . percent < = 0 )
cl . cshifts [ CSHIFT_DAMAGE ] . percent = 0 ;
// drop the bonus value
cl . cshifts [ CSHIFT_BONUS ] . percent - = host_frametime * 100 ;
if ( cl . cshifts [ CSHIFT_BONUS ] . percent < = 0 )
cl . cshifts [ CSHIFT_BONUS ] . percent = 0 ;
if ( blend_changed )
V_CalcBlend ( ) ;
}
/*
= = = = = = = = = = = =
V_PolyBlend - - johnfitz - - moved here from gl_rmain . c , and rewritten to use glOrtho
= = = = = = = = = = = =
*/
void V_PolyBlend ( void )
{
if ( ! gl_polyblend . value | | ! v_blend [ 3 ] )
return ;
GL_DisableMultitexture ( ) ;
glDisable ( GL_TEXTURE_2D ) ;
glDisable ( GL_DEPTH_TEST ) ;
glEnable ( GL_BLEND ) ;
2017-09-17 02:12:53 +00:00
if ( premul_hud )
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
else
glDisable ( GL_ALPHA_TEST ) ;
2010-02-15 23:26:55 +00:00
glMatrixMode ( GL_PROJECTION ) ;
2017-09-17 02:12:53 +00:00
glLoadIdentity ( ) ;
2010-02-15 23:26:55 +00:00
glOrtho ( 0 , 1 , 1 , 0 , - 99999 , 99999 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
2017-09-17 02:12:53 +00:00
glLoadIdentity ( ) ;
2010-02-15 23:26:55 +00:00
glBegin ( GL_QUADS ) ;
2022-10-13 17:28:02 +00:00
glColor4fv ( v_blend ) ; // inside glBegin / glEnd to workaround an AMD driver bug
2010-02-15 23:26:55 +00:00
glVertex2f ( 0 , 0 ) ;
glVertex2f ( 1 , 0 ) ;
glVertex2f ( 1 , 1 ) ;
glVertex2f ( 0 , 1 ) ;
glEnd ( ) ;
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_TEXTURE_2D ) ;
2017-09-17 02:12:53 +00:00
if ( premul_hud )
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
else
{
glDisable ( GL_BLEND ) ;
glEnable ( GL_ALPHA_TEST ) ;
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
VIEW RENDERING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
CalcGunAngle
= = = = = = = = = = = = = = = = = =
*/
void CalcGunAngle ( void )
{
2023-07-24 07:08:14 +00:00
cl . viewent . angles [ ROLL ] = - v_idlescale . value * sin ( cl . time * v_iroll_cycle . value ) * v_iroll_level . value - r_refdef . viewangles [ ROLL ] ;
cl . viewent . angles [ PITCH ] = - v_idlescale . value * sin ( cl . time * v_ipitch_cycle . value ) * v_ipitch_level . value ;
cl . viewent . angles [ YAW ] = - v_idlescale . value * sin ( cl . time * v_iyaw_cycle . value ) * v_iyaw_level . value ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = =
V_BoundOffsets
= = = = = = = = = = = = = =
*/
void V_BoundOffsets ( void )
{
entity_t * ent ;
2017-09-17 02:12:53 +00:00
ent = & cl . entities [ cl . viewentity ] ;
2010-02-15 23:26:55 +00:00
// absolutely bound refresh reletive to entity clipping hull
// so the view can never be inside a solid wall
if ( r_refdef . vieworg [ 0 ] < ent - > origin [ 0 ] - 14 )
r_refdef . vieworg [ 0 ] = ent - > origin [ 0 ] - 14 ;
else if ( r_refdef . vieworg [ 0 ] > ent - > origin [ 0 ] + 14 )
r_refdef . vieworg [ 0 ] = ent - > origin [ 0 ] + 14 ;
if ( r_refdef . vieworg [ 1 ] < ent - > origin [ 1 ] - 14 )
r_refdef . vieworg [ 1 ] = ent - > origin [ 1 ] - 14 ;
else if ( r_refdef . vieworg [ 1 ] > ent - > origin [ 1 ] + 14 )
r_refdef . vieworg [ 1 ] = ent - > origin [ 1 ] + 14 ;
if ( r_refdef . vieworg [ 2 ] < ent - > origin [ 2 ] - 22 )
r_refdef . vieworg [ 2 ] = ent - > origin [ 2 ] - 22 ;
else if ( r_refdef . vieworg [ 2 ] > ent - > origin [ 2 ] + 30 )
r_refdef . vieworg [ 2 ] = ent - > origin [ 2 ] + 30 ;
}
/*
= = = = = = = = = = = = = =
V_AddIdle
Idle swaying
= = = = = = = = = = = = = =
*/
void V_AddIdle ( void )
{
r_refdef . viewangles [ ROLL ] + = v_idlescale . value * sin ( cl . time * v_iroll_cycle . value ) * v_iroll_level . value ;
r_refdef . viewangles [ PITCH ] + = v_idlescale . value * sin ( cl . time * v_ipitch_cycle . value ) * v_ipitch_level . value ;
r_refdef . viewangles [ YAW ] + = v_idlescale . value * sin ( cl . time * v_iyaw_cycle . value ) * v_iyaw_level . value ;
}
/*
= = = = = = = = = = = = = =
V_CalcViewRoll
Roll is induced by movement and damage
= = = = = = = = = = = = = =
*/
void V_CalcViewRoll ( void )
{
float side ;
2017-09-17 02:12:53 +00:00
side = V_CalcRoll ( cl . entities [ cl . viewentity ] . angles , cl . velocity ) ;
2010-02-15 23:26:55 +00:00
r_refdef . viewangles [ ROLL ] + = side ;
if ( v_dmg_time > 0 )
{
r_refdef . viewangles [ ROLL ] + = v_dmg_time / v_kicktime . value * v_dmg_roll ;
r_refdef . viewangles [ PITCH ] + = v_dmg_time / v_kicktime . value * v_dmg_pitch ;
v_dmg_time - = host_frametime ;
}
if ( cl . stats [ STAT_HEALTH ] < = 0 )
{
r_refdef . viewangles [ ROLL ] = 80 ; // dead view angle
return ;
}
}
/*
= = = = = = = = = = = = = = = = = =
V_CalcIntermissionRefdef
= = = = = = = = = = = = = = = = = =
*/
void V_CalcIntermissionRefdef ( void )
{
entity_t * ent , * view ;
float old ;
// ent is the player model (visible when out of body)
2017-09-17 02:12:53 +00:00
ent = & cl . entities [ cl . viewentity ] ;
2010-02-15 23:26:55 +00:00
// view is the weapon model (only visible from inside body)
view = & cl . viewent ;
VectorCopy ( ent - > origin , r_refdef . vieworg ) ;
VectorCopy ( ent - > angles , r_refdef . viewangles ) ;
view - > model = NULL ;
// allways idle in intermission
old = v_idlescale . value ;
v_idlescale . value = 1 ;
V_AddIdle ( ) ;
v_idlescale . value = old ;
}
/*
= = = = = = = = = = = = = = = = = =
V_CalcRefdef
= = = = = = = = = = = = = = = = = =
*/
void V_CalcRefdef ( void )
{
entity_t * ent , * view ;
int i ;
vec3_t forward , right , up ;
vec3_t angles ;
float bob ;
static float oldz = 0 ;
static vec3_t punch = { 0 , 0 , 0 } ; //johnfitz -- v_gunkick
float delta ; //johnfitz -- v_gunkick
V_DriftPitch ( ) ;
// ent is the player model (visible when out of body)
2017-09-17 02:12:53 +00:00
ent = & cl . entities [ cl . viewentity ] ;
2010-02-15 23:26:55 +00:00
// view is the weapon model (only visible from inside body)
view = & cl . viewent ;
// transform the view offset by the model's matrix to get the offset from
// model origin for the view
ent - > angles [ YAW ] = cl . viewangles [ YAW ] ; // the model should face the view dir
ent - > angles [ PITCH ] = - cl . viewangles [ PITCH ] ; // the model should face the view dir
bob = V_CalcBob ( ) ;
// refresh position
VectorCopy ( ent - > origin , r_refdef . vieworg ) ;
2017-09-17 02:12:53 +00:00
r_refdef . vieworg [ 2 ] + = cl . stats [ STAT_VIEWHEIGHT ] + bob ;
2010-02-15 23:26:55 +00:00
// never let it sit exactly on a node line, because a water plane can
// dissapear when viewed with the eye exactly on it.
// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis
r_refdef . vieworg [ 0 ] + = 1.0 / 32 ;
r_refdef . vieworg [ 1 ] + = 1.0 / 32 ;
r_refdef . vieworg [ 2 ] + = 1.0 / 32 ;
VectorCopy ( cl . viewangles , r_refdef . viewangles ) ;
V_CalcViewRoll ( ) ;
V_AddIdle ( ) ;
// offsets
angles [ PITCH ] = - ent - > angles [ PITCH ] ; // because entity pitches are actually backward
angles [ YAW ] = ent - > angles [ YAW ] ;
angles [ ROLL ] = ent - > angles [ ROLL ] ;
AngleVectors ( angles , forward , right , up ) ;
if ( cl . maxclients < = 1 ) //johnfitz -- moved cheat-protection here from V_RenderView
for ( i = 0 ; i < 3 ; i + + )
r_refdef . vieworg [ i ] + = scr_ofsx . value * forward [ i ] + scr_ofsy . value * right [ i ] + scr_ofsz . value * up [ i ] ;
V_BoundOffsets ( ) ;
2023-07-24 07:08:14 +00:00
// set up gun stuff
2010-02-15 23:26:55 +00:00
CalcGunAngle ( ) ;
2023-07-24 07:08:14 +00:00
view - > eflags = EFLAGS_VIEWMODEL ;
VectorScale ( forward , 1.0 / 32 , view - > origin ) ; //bias it very slightly sideways (so it shifts slightly when turning to mimic the 1/32 bias that used to affect it before we changed how viewmodels work)
view - > origin [ 0 ] = bob * 0.4 ; //and bob it forwards
view - > alpha = ENTALPHA_ENCODE ( r_drawviewmodel . value ) ;
2010-02-15 23:26:55 +00:00
//johnfitz -- removed all gun position fudging code (was used to keep gun from getting covered by sbar)
2017-08-19 01:35:54 +00:00
//MarkV -- restored this with r_viewmodel_quake cvar
if ( r_viewmodel_quake . value )
{
if ( scr_viewsize . value = = 110 )
view - > origin [ 2 ] + = 1 ;
else if ( scr_viewsize . value = = 100 )
view - > origin [ 2 ] + = 2 ;
else if ( scr_viewsize . value = = 90 )
view - > origin [ 2 ] + = 1 ;
else if ( scr_viewsize . value = = 80 )
view - > origin [ 2 ] + = 0.5 ;
}
2010-02-15 23:26:55 +00:00
view - > model = cl . model_precache [ cl . stats [ STAT_WEAPON ] ] ;
view - > frame = cl . stats [ STAT_WEAPONFRAME ] ;
2023-03-18 11:14:40 +00:00
view - > netstate = nullentitystate ;
2010-02-15 23:26:55 +00:00
//johnfitz -- v_gunkick
if ( v_gunkick . value = = 1 ) //original quake kick
VectorAdd ( r_refdef . viewangles , cl . punchangle , r_refdef . viewangles ) ;
if ( v_gunkick . value = = 2 ) //lerped kick
{
for ( i = 0 ; i < 3 ; i + + )
if ( punch [ i ] ! = v_punchangles [ 0 ] [ i ] )
{
2020-10-13 17:11:34 +00:00
double interval = v_punchangles_times [ 0 ] - v_punchangles_times [ 1 ] ;
if ( interval > 0.1 ) interval = 0.1 ;
2010-02-15 23:26:55 +00:00
//speed determined by how far we need to lerp in 1/10th of a second
2020-10-13 17:11:34 +00:00
delta = ( v_punchangles [ 0 ] [ i ] - v_punchangles [ 1 ] [ i ] ) * host_frametime / interval ;
2010-02-15 23:26:55 +00:00
if ( delta > 0 )
2011-01-10 10:35:40 +00:00
punch [ i ] = q_min ( punch [ i ] + delta , v_punchangles [ 0 ] [ i ] ) ;
2010-02-15 23:26:55 +00:00
else if ( delta < 0 )
2011-01-10 10:35:40 +00:00
punch [ i ] = q_max ( punch [ i ] + delta , v_punchangles [ 0 ] [ i ] ) ;
2010-02-15 23:26:55 +00:00
}
VectorAdd ( r_refdef . viewangles , punch , r_refdef . viewangles ) ;
}
//johnfitz
// smooth out stair step ups
if ( ! noclip_anglehack & & cl . onground & & ent - > origin [ 2 ] - oldz > 0 ) //johnfitz -- added exception for noclip
//FIXME: noclip_anglehack is set on the server, so in a nonlocal game this won't work.
{
float steptime ;
steptime = cl . time - cl . oldtime ;
if ( steptime < 0 )
//FIXME I_Error ("steptime < 0");
steptime = 0 ;
oldz + = steptime * 80 ;
if ( oldz > ent - > origin [ 2 ] )
oldz = ent - > origin [ 2 ] ;
if ( ent - > origin [ 2 ] - oldz > 12 )
oldz = ent - > origin [ 2 ] - 12 ;
r_refdef . vieworg [ 2 ] + = oldz - ent - > origin [ 2 ] ;
}
else
oldz = ent - > origin [ 2 ] ;
if ( chase_active . value )
Chase_UpdateForDrawing ( ) ; //johnfitz
}
2022-02-27 19:36:47 +00:00
/*
= = = = = = = = = = = = = = = = = =
V_RestoreAngles
Resets the viewentity angles to the last values received from the server
( undoing the manual adjustments performed by V_CalcRefdef )
= = = = = = = = = = = = = = = = = =
*/
void V_RestoreAngles ( void )
{
2022-04-27 21:32:40 +00:00
entity_t * ent = & cl . entities [ cl . viewentity ] ;
2022-02-27 19:36:47 +00:00
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > angles ) ;
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
V_RenderView
The player ' s clipping box goes from ( - 16 - 16 - 24 ) to ( 16 16 32 ) from
the entity origin , so any view position inside that will be valid
= = = = = = = = = = = = = = = = = =
*/
extern vrect_t scr_vrect ;
void V_RenderView ( void )
{
if ( con_forcedup )
return ;
if ( cl . intermission )
V_CalcIntermissionRefdef ( ) ;
else if ( ! cl . paused /* && (cl.maxclients > 1 || key_dest == key_game) */ )
V_CalcRefdef ( ) ;
//johnfitz -- removed lcd code
R_RenderView ( ) ;
V_PolyBlend ( ) ; //johnfitz -- moved here from R_Renderview ();
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
INIT
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = =
V_Init
= = = = = = = = = = = = =
*/
void V_Init ( void )
{
Cmd_AddCommand ( " v_cshift " , V_cshift_f ) ;
Cmd_AddCommand ( " bf " , V_BonusFlash_f ) ;
Cmd_AddCommand ( " centerview " , V_StartPitchDrift ) ;
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & v_centermove ) ;
Cvar_RegisterVariable ( & v_centerspeed ) ;
Cvar_RegisterVariable ( & v_iyaw_cycle ) ;
Cvar_RegisterVariable ( & v_iroll_cycle ) ;
Cvar_RegisterVariable ( & v_ipitch_cycle ) ;
Cvar_RegisterVariable ( & v_iyaw_level ) ;
Cvar_RegisterVariable ( & v_iroll_level ) ;
Cvar_RegisterVariable ( & v_ipitch_level ) ;
Cvar_RegisterVariable ( & v_idlescale ) ;
Cvar_RegisterVariable ( & crosshair ) ;
Cvar_RegisterVariable ( & gl_cshiftpercent ) ;
2017-10-03 19:49:04 +00:00
Cvar_RegisterVariable ( & gl_cshiftpercent_contents ) ; // QuakeSpasm
Cvar_RegisterVariable ( & gl_cshiftpercent_damage ) ; // QuakeSpasm
Cvar_RegisterVariable ( & gl_cshiftpercent_bonus ) ; // QuakeSpasm
Cvar_RegisterVariable ( & gl_cshiftpercent_powerup ) ; // QuakeSpasm
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & scr_ofsx ) ;
Cvar_RegisterVariable ( & scr_ofsy ) ;
Cvar_RegisterVariable ( & scr_ofsz ) ;
Cvar_RegisterVariable ( & cl_rollspeed ) ;
Cvar_RegisterVariable ( & cl_rollangle ) ;
Cvar_RegisterVariable ( & cl_bob ) ;
Cvar_RegisterVariable ( & cl_bobcycle ) ;
Cvar_RegisterVariable ( & cl_bobup ) ;
Cvar_RegisterVariable ( & v_kicktime ) ;
Cvar_RegisterVariable ( & v_kickroll ) ;
Cvar_RegisterVariable ( & v_kickpitch ) ;
Cvar_RegisterVariable ( & v_gunkick ) ; //johnfitz
2022-09-05 20:56:40 +00:00
2017-08-19 01:35:54 +00:00
Cvar_RegisterVariable ( & r_viewmodel_quake ) ; //MarkV
2010-02-15 23:26:55 +00:00
}