2004-08-23 00:15:46 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
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 included ( GNU . txt ) 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 .
*/
/* ZOID
*
* Player camera tracking in Spectator mode
*
* This takes over player controls for spectator automatic camera .
* Player moves as a spectator , but the camera tracks and enemy player
*/
# include "quakedef.h"
# include "winquake.h"
# define PM_SPECTATORMAXSPEED 500
# define PM_STOPSPEED 100
# define PM_MAXSPEED 320
# define BUTTON_JUMP 2
# define BUTTON_ATTACK 1
# define MAX_ANGLE_TURN 10
char cl_spectatorgroup [ ] = " Spectator Tracking " ;
2015-06-12 14:44:50 +00:00
enum
{
TM_USER , //user hit jump and changed pov explicitly
TM_HIGHTRACK , //tracking the player with the highest frags
TM_KILLER , //switch to the previous person's killer.
TM_MODHINTS , //using the mod's //at hints
TM_STATS //parsing mvd stats and making our own choices
} autotrackmode ;
char * autotrack_statsrule ;
static void QDECL CL_AutoTrackChanged ( cvar_t * v , char * oldval )
{
Cam_AutoTrack_Update ( v - > string ) ;
}
2004-08-23 00:15:46 +00:00
// track high fragger
2016-09-08 19:04:35 +00:00
cvar_t cl_autotrack_team = CVARD ( " cl_autotrack_team " , " " , " Specifies a team name that should be auto-tracked (players on other teams will not be candidates for autotracking). Accepts * and ? wildcards for awkward chars. " ) ;
cvar_t cl_autotrack = CVARCD ( " cl_autotrack " , " auto " , CL_AutoTrackChanged , " Specifies the default tracking mode at the start of the map. Use the 'autotrack' command to reset/apply an auto-tracking mode without changing the default. \n Valid values are: high, ^hkiller^h, mod, user. Other values are treated as weighting scripts for mvd playback, where available. " ) ;
cvar_t cl_hightrack = CVARD ( " cl_hightrack " , " 0 " , " Obsolete. If you want hightrack, use '[cl_]autotrack high' instead. " ) ;
2004-08-23 00:15:46 +00:00
2015-06-12 14:44:50 +00:00
//cvar_t cl_camera_maxpitch = {"cl_camera_maxpitch", "10" };
//cvar_t cl_camera_maxyaw = {"cl_camera_maxyaw", "30" };
2016-09-08 19:04:35 +00:00
cvar_t cl_chasecam = CVAR ( " cl_chasecam " , " 1 " ) ;
cvar_t cl_selfcam = CVAR ( " cl_selfcam " , " 1 " ) ;
2004-08-23 00:15:46 +00:00
2015-06-12 14:44:50 +00:00
void Cam_AutoTrack_Update ( const char * mode )
{
if ( ! mode )
mode = cl_autotrack . string ;
Z_Free ( autotrack_statsrule ) ;
autotrack_statsrule = NULL ;
if ( ! * mode | | ! Q_strcasecmp ( mode , " auto " ) )
{
2015-07-30 16:26:15 +00:00
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
{
autotrackmode = TM_STATS ;
autotrack_statsrule = Z_StrDup ( " " ) ; //default
}
else if ( cl_hightrack . ival )
2015-06-12 14:44:50 +00:00
autotrackmode = TM_HIGHTRACK ;
else
autotrackmode = TM_MODHINTS ;
}
else if ( ! Q_strcasecmp ( mode , " high " ) )
autotrackmode = TM_HIGHTRACK ;
else if ( ! Q_strcasecmp ( mode , " killer " ) )
autotrackmode = TM_KILLER ;
else if ( ! Q_strcasecmp ( mode , " mod " ) )
autotrackmode = TM_MODHINTS ;
else if ( ! Q_strcasecmp ( mode , " user " ) | | ! Q_strcasecmp ( mode , " off " ) )
autotrackmode = TM_USER ;
2015-07-30 16:26:15 +00:00
else if ( ! Q_strcasecmp ( mode , " stats " ) )
{
autotrackmode = TM_STATS ;
autotrack_statsrule = NULL ;
}
2015-06-12 14:44:50 +00:00
else
{
autotrackmode = TM_STATS ;
autotrack_statsrule = Z_StrDup ( mode ) ;
}
}
static void Cam_AutoTrack_f ( void )
{
if ( * Cmd_Argv ( 1 ) )
Cam_AutoTrack_Update ( Cmd_Argv ( 1 ) ) ;
else
Cam_AutoTrack_Update ( NULL ) ;
}
2015-07-30 16:26:15 +00:00
static float CL_TrackScoreProp ( player_info_t * pl , char rule , float * weights )
2015-06-12 14:44:50 +00:00
{
2016-07-15 12:26:24 +00:00
# ifdef QUAKESTATS
2015-07-30 16:26:15 +00:00
float r ;
2016-07-15 12:26:24 +00:00
# endif
2015-07-30 16:26:15 +00:00
switch ( rule )
2015-06-12 14:44:50 +00:00
{
2015-08-04 15:16:24 +00:00
case ' . ' : //currently being tracked. combine with currently alive or something
{
int i ;
for ( i = 0 ; i < cl . splitclients ; i + + )
{
//not valid if an earlier view is tracking it.
if ( Cam_TrackNum ( & cl . playerview [ i ] ) = = pl - cl . players )
return 1 ;
}
return 0 ;
}
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2015-07-30 16:26:15 +00:00
case ' a ' : //armour value
return pl - > statsf [ STAT_ARMOR ] ;
case ' h ' :
return pl - > statsf [ STAT_HEALTH ] ;
case ' A ' : //armour type
if ( pl - > stats [ STAT_ITEMS ] & IT_ARMOR3 ) r = weights [ 10 ] ;
else if ( pl - > stats [ STAT_ITEMS ] & IT_ARMOR2 ) r = weights [ 9 ] ;
else if ( pl - > stats [ STAT_ITEMS ] & IT_ARMOR1 ) r = weights [ 8 ] ;
else r = 0 ;
return r ;
case ' W ' : //best weapon
r = 0 ;
if ( r < weights [ 0 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_AXE ) ) r = weights [ 0 ] ;
if ( r < weights [ 1 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_SHOTGUN ) ) r = weights [ 1 ] ;
if ( r < weights [ 2 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_SUPER_SHOTGUN ) ) r = weights [ 2 ] ;
if ( r < weights [ 3 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_NAILGUN ) ) r = weights [ 3 ] ;
if ( r < weights [ 4 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_SUPER_NAILGUN ) ) r = weights [ 4 ] ;
if ( r < weights [ 5 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_GRENADE_LAUNCHER ) ) r = weights [ 5 ] ;
if ( r < weights [ 6 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_ROCKET_LAUNCHER ) ) r = weights [ 6 ] ;
if ( r < weights [ 7 ] & & ( pl - > stats [ STAT_ITEMS ] & IT_LIGHTNING ) ) r = weights [ 7 ] ;
return r ;
case ' p ' : //powerups held
r = 0 ;
r + = ( pl - > stats [ STAT_ITEMS ] & IT_INVISIBILITY ) ? weights [ 11 ] : 0 ;
r + = ( pl - > stats [ STAT_ITEMS ] & IT_QUAD ) ? weights [ 12 ] : 0 ;
r + = ( pl - > stats [ STAT_ITEMS ] & IT_INVULNERABILITY ) ? weights [ 13 ] : 0 ;
return r ;
2015-09-01 04:45:15 +00:00
# endif
2015-07-30 16:26:15 +00:00
case ' f ' : //frags
return pl - > frags ;
// case 'F': //team frags
// return 0;
2017-07-10 15:40:42 +00:00
# ifdef QUAKEHUD
2015-07-30 16:26:15 +00:00
case ' g ' : //deaths
return Stats_GetDeaths ( pl - cl . players ) ;
2017-07-10 15:40:42 +00:00
# endif
2015-07-30 16:26:15 +00:00
case ' u ' : //userid
return pl - cl . players ;
2015-08-04 15:16:24 +00:00
case ' c ' : //'current run time'
case ' C ' : //'current run frags'
case ' d ' : //'current run teamfrags'
case ' I ' : //ssg grabs
case ' j ' : //ng grabs
case ' J ' : //sng grabs
case ' k ' : //gl grabs
case ' K ' : //gl lost
case ' l ' : //rl grabs
case ' L ' : //rl lost
case ' m ' : //lg grabs
case ' M ' : //lg lost
case ' n ' : //mh grabs
case ' N ' : //ga grabs
case ' o ' : //ya grabs
case ' O ' : //ra grabs
case ' v ' : //average run time
case ' V ' : //average run frags
case ' w ' : //average run teamfrags
case ' x ' : //ring grabs
case ' X ' : //ring losts
case ' y ' : //quad grabs
case ' Y ' : //quad losts
case ' z ' : //pent grabs
2015-07-30 16:26:15 +00:00
default :
return 0 ;
}
}
2015-08-04 15:16:24 +00:00
# define PRI_TOP 3
# define PRI_LOGIC 3
2015-07-30 16:26:15 +00:00
# define PRI_ADD 2
# define PRI_MUL 1
# define PRI_VAL 0
static float CL_TrackScore ( player_info_t * pl , char * * rule , float * weights , int pri )
{
float l , r ;
char * s = * rule ;
while ( * s = = ' ' | | * s = = ' \t ' )
s + + ;
if ( ! pri )
{
2015-08-04 15:16:24 +00:00
if ( * s = = ' ! ' )
{
s + + ;
l = ! CL_TrackScore ( pl , & s , weights , pri ) ;
}
2015-07-30 16:26:15 +00:00
if ( * s = = ' ( ' )
2015-06-12 14:44:50 +00:00
{
2015-07-30 16:26:15 +00:00
l = CL_TrackScore ( pl , & s , weights , PRI_TOP ) ;
while ( * s = = ' ' | | * s = = ' \t ' )
s + + ;
if ( * s = = ' ) ' )
s + + ;
}
else if ( * s = = ' % ' )
{
l = CL_TrackScoreProp ( pl , * + + s , weights ) ;
s + + ;
}
else if ( * s = = ' # ' )
{
int i = strtoul ( s + 1 , & s , 0 ) ;
if ( i > = 0 & & i < MAX_CL_STATS )
l = pl - > statsf [ i ] ;
else
l = 0 ;
2015-06-12 14:44:50 +00:00
}
else
2015-07-30 16:26:15 +00:00
l = strtod ( s , & s ) ;
while ( * s = = ' ' | | * s = = ' \t ' )
s + + ;
}
else
l = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
2015-06-12 14:44:50 +00:00
2015-07-30 16:26:15 +00:00
for ( ; ; )
{
if ( pri = = PRI_MUL )
2015-06-12 14:44:50 +00:00
{
2015-07-30 16:26:15 +00:00
if ( * s = = ' * ' )
{
s + + ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l * = r ;
continue ;
}
else if ( * s = = ' / ' )
{
s + + ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l / = r ;
continue ;
}
2015-06-12 14:44:50 +00:00
}
2015-07-30 16:26:15 +00:00
else if ( pri = = PRI_ADD )
{
if ( * s = = ' + ' )
{
s + + ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l + = r ;
continue ;
}
else if ( * s = = ' - ' )
{
s + + ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l - = r ;
continue ;
}
}
2015-08-04 15:16:24 +00:00
else if ( pri = = PRI_LOGIC )
{
if ( * s = = ' | ' & & s [ 1 ] = = ' | ' )
{
s + = 2 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l | | r ;
continue ;
}
else if ( * s = = ' & ' & & s [ 1 ] = = ' & ' )
{
s + = 2 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l & & r ;
continue ;
}
else if ( * s = = ' & ' )
{
s + + ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = ( int ) l & ( int ) r ;
continue ;
}
else if ( * s = = ' | ' )
{
s + + ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = ( int ) l | ( int ) r ;
continue ;
}
else if ( * s = = ' > ' & & s [ 1 ] = = ' = ' )
{
s + = 2 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l > = r ;
continue ;
}
else if ( * s = = ' < ' & & s [ 1 ] = = ' = ' )
{
s + = 2 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l < = r ;
continue ;
}
else if ( * s = = ' > ' )
{
s + = 1 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l > r ;
continue ;
}
else if ( * s = = ' < ' )
{
s + = 1 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l > r ;
continue ;
}
else if ( * s = = ' ! ' & & s [ 1 ] = = ' = ' )
{
s + = 2 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l ! = r ;
continue ;
}
else if ( * s = = ' = ' & & s [ 1 ] = = ' = ' )
{
s + = 2 ;
r = CL_TrackScore ( pl , & s , weights , pri - 1 ) ;
l = l ! = r ;
continue ;
}
}
2015-07-30 16:26:15 +00:00
break ;
2015-06-12 14:44:50 +00:00
}
2015-07-30 16:26:15 +00:00
* rule = s ;
return l ;
2015-06-12 14:44:50 +00:00
}
2016-01-18 05:22:07 +00:00
static qboolean CL_MayAutoTrack ( int seat , int player )
2015-06-24 17:59:57 +00:00
{
if ( player < 0 )
return false ;
if ( ! cl . players [ player ] . userid | | ! cl . players [ player ] . name [ 0 ] | | cl . players [ player ] . spectator )
return false ;
2016-01-18 05:22:07 +00:00
if ( * cl_autotrack_team . string & & ! wildcmp ( cl_autotrack_team . string , cl . players [ player ] . team ) )
return false ;
2015-06-24 17:59:57 +00:00
for ( seat - - ; seat > = 0 ; seat - - )
{
//not valid if an earlier view is tracking it.
if ( Cam_TrackNum ( & cl . playerview [ seat ] ) = = player )
return false ;
}
return true ;
}
2015-06-12 14:44:50 +00:00
//returns the player with the highest frags
static int CL_FindHighTrack ( int seat , char * rule )
{
int j = - 1 ;
2015-07-30 16:26:15 +00:00
int i ;
2015-06-12 14:44:50 +00:00
float max , score ;
player_info_t * s ;
2015-07-30 16:26:15 +00:00
float weights [ 14 ] ;
char * p ;
2015-08-04 15:16:24 +00:00
qboolean instant ;
instant = ( rule & & * rule = = ' ! ' ) ;
if ( instant )
rule + + ;
2015-07-30 16:26:15 +00:00
if ( rule & & * rule = = ' [ ' )
{
rule + + ;
weights [ 0 ] = strtod ( rule , & rule ) ; //axe
weights [ 1 ] = strtod ( rule , & rule ) ; //shot
weights [ 2 ] = strtod ( rule , & rule ) ; //sshot
weights [ 3 ] = strtod ( rule , & rule ) ; //nail
weights [ 4 ] = strtod ( rule , & rule ) ; //snail
weights [ 5 ] = strtod ( rule , & rule ) ; //gren
weights [ 6 ] = strtod ( rule , & rule ) ; //rock
weights [ 7 ] = strtod ( rule , & rule ) ; //lg
weights [ 8 ] = strtod ( rule , & rule ) ; //ga
weights [ 9 ] = strtod ( rule , & rule ) ; //ya
weights [ 10 ] = strtod ( rule , & rule ) ; //ra
weights [ 11 ] = strtod ( rule , & rule ) ; //ring
weights [ 12 ] = strtod ( rule , & rule ) ; //quad
weights [ 13 ] = strtod ( rule , & rule ) ; //pent
if ( * rule = = ' ] ' )
rule + + ;
}
else
{
weights [ 0 ] = 1 ; //axe
weights [ 1 ] = 2 ; //shot
weights [ 2 ] = 3 ; //sshot
weights [ 3 ] = 2 ; //nail
weights [ 4 ] = 3 ; //snail
weights [ 5 ] = 3 ; //gren
weights [ 6 ] = 8 ; //rock
weights [ 7 ] = 8 ; //lg
weights [ 8 ] = 1 ; //ga
weights [ 9 ] = 2 ; //ya
weights [ 10 ] = 3 ; //ra
weights [ 11 ] = 500 ; //ring
weights [ 12 ] = 900 ; //quad
weights [ 13 ] = 1000 ; //pent
}
if ( ! rule | | ! * rule )
rule = " %a * %A + 50 * %W + %p + %f " ;
2015-06-12 14:44:50 +00:00
//set a default to the currently tracked player, to reuse the current player we're tracking if someone lower equalises.
j = cl . playerview [ seat ] . cam_spec_track ;
2016-01-18 05:22:07 +00:00
if ( CL_MayAutoTrack ( seat , j ) )
2015-07-30 16:26:15 +00:00
{
p = rule ;
max = CL_TrackScore ( & cl . players [ j ] , & p , weights , PRI_TOP ) ;
}
2015-06-12 14:44:50 +00:00
else
2015-06-14 01:28:01 +00:00
{
2015-06-12 14:44:50 +00:00
max = - 9999 ;
2015-06-14 01:28:01 +00:00
j = - 1 ;
}
2015-06-12 14:44:50 +00:00
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
{
s = & cl . players [ i ] ;
2015-07-30 16:26:15 +00:00
if ( j = = i ) //this was our default.
continue ;
2016-01-18 05:22:07 +00:00
if ( ! CL_MayAutoTrack ( seat , i ) )
2015-07-30 16:26:15 +00:00
continue ;
if ( cl . teamplay & & seat & & cl . playerview [ 0 ] . cam_spec_track > = 0 & & strcmp ( cl . players [ cl . playerview [ 0 ] . cam_spec_track ] . team , s - > team ) )
continue ; //when using multiview, keep tracking the team
p = rule ;
score = CL_TrackScore ( s , & p , weights , PRI_TOP ) ;
2015-06-24 17:59:57 +00:00
if ( score > max )
2015-06-12 14:44:50 +00:00
{
2015-07-30 16:26:15 +00:00
max = score ;
j = i ;
}
}
if ( j = = - 1 & & cl . teamplay & & seat )
{
//do it again, but with the teamplay check inverted
2016-01-18 05:22:07 +00:00
//fixme: should probably reduce seat count instead, at least in demos.
2015-07-30 16:26:15 +00:00
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
{
s = & cl . players [ i ] ;
2015-06-12 14:44:50 +00:00
if ( j = = i ) //this was our default.
continue ;
2016-01-18 05:22:07 +00:00
if ( ! CL_MayAutoTrack ( seat , i ) )
2015-06-24 17:59:57 +00:00
continue ;
2015-07-30 16:26:15 +00:00
if ( ! ( cl . teamplay & & seat & & cl . playerview [ 0 ] . cam_spec_track > = 0 & & strcmp ( cl . players [ cl . playerview [ 0 ] . cam_spec_track ] . team , s - > team ) ) )
2015-06-12 14:44:50 +00:00
continue ; //when using multiview, keep tracking the team
2015-07-30 16:26:15 +00:00
p = rule ;
score = CL_TrackScore ( s , & p , weights , PRI_TOP ) ;
if ( score > max )
{
max = score ;
j = i ;
}
2015-06-12 14:44:50 +00:00
}
}
2015-08-04 15:16:24 +00:00
2016-01-18 05:22:07 +00:00
if ( j ! = - 1 & & CL_MayAutoTrack ( seat , cl . playerview [ seat ] . cam_spec_track ) & & ! instant )
2015-08-04 15:16:24 +00:00
{
i = cl . playerview [ seat ] . cam_spec_track ;
//extra hacks to prevent 'random' switching mid-game
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2015-08-04 15:16:24 +00:00
if ( ( cl . players [ j ] . stats [ STAT_ITEMS ] ^ cl . players [ i ] . stats [ STAT_ITEMS ] ) & ( IT_INVULNERABILITY | IT_QUAD ) )
; //don't block if the players have different powerups
else if ( ( cl . players [ j ] . stats [ STAT_ITEMS ] & ( IT_ROCKET_LAUNCHER | IT_LIGHTNING ) ) & & ! ( cl . players [ i ] . stats [ STAT_ITEMS ] & ( IT_ROCKET_LAUNCHER | IT_LIGHTNING ) ) )
; //don't block the switch if the new player has a decent weapon, and the guy we're tracking does not.
2018-08-04 19:00:19 +00:00
else if ( ( cl . players [ j ] . stats [ STAT_ITEMS ] & ( IT_ROCKET_LAUNCHER | IT_INVULNERABILITY ) ) = = ( IT_ROCKET_LAUNCHER | IT_INVULNERABILITY ) & & ( cl . players [ i ] . stats [ STAT_ITEMS ] & ( IT_ROCKET_LAUNCHER | IT_INVULNERABILITY ) ) ! = ( IT_ROCKET_LAUNCHER | IT_INVULNERABILITY ) )
2015-08-04 15:16:24 +00:00
; //don't block if we're switching to someone with pent+rl from someone that does not.
else
2015-09-01 04:45:15 +00:00
# endif
2015-08-04 15:16:24 +00:00
return cl . playerview [ seat ] . cam_spec_track ;
}
2015-06-12 14:44:50 +00:00
return j ;
}
static int CL_AutoTrack_Choose ( int seat )
{
int best = - 1 ;
if ( autotrackmode = = TM_KILLER )
2015-06-14 01:28:01 +00:00
best = cl . autotrack_killer ;
if ( autotrackmode = = TM_MODHINTS & & seat = = 0 & & cl . autotrack_hint > = 0 )
best = cl . autotrack_hint ;
2015-07-30 16:26:15 +00:00
if ( autotrackmode = = TM_STATS & & ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV ) )
2015-06-12 14:44:50 +00:00
best = CL_FindHighTrack ( seat , autotrack_statsrule ) ;
if ( autotrackmode = = TM_HIGHTRACK | | best = = - 1 )
2015-07-30 16:26:15 +00:00
best = CL_FindHighTrack ( seat , " %f " ) ;
2015-06-12 14:44:50 +00:00
//TM_USER should generally avoid autotracking
2015-06-14 01:28:01 +00:00
cl . autotrack_killer = best ; //killer should continue to track whatever is currently tracked until its changed by frag message parsing
2015-06-12 14:44:50 +00:00
return best ;
}
2004-08-23 00:15:46 +00:00
2015-04-14 23:12:17 +00:00
static int Cam_FindSortedPlayer ( int number ) ;
2004-08-23 00:15:46 +00:00
2006-09-17 00:59:22 +00:00
int selfcam = 1 ;
2004-08-23 00:15:46 +00:00
static float vlen ( vec3_t v )
{
return sqrt ( v [ 0 ] * v [ 0 ] + v [ 1 ] * v [ 1 ] + v [ 2 ] * v [ 2 ] ) ;
}
// returns true if weapon model should be drawn in camera mode
2013-06-23 02:17:02 +00:00
qboolean Cam_DrawViewModel ( playerview_t * pv )
2004-08-23 00:15:46 +00:00
{
2017-05-28 15:42:32 +00:00
if ( pv - > spectator )
2006-09-17 00:59:22 +00:00
{
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state = = CAM_EYECAM & & cl_chasecam . ival )
2006-09-17 00:59:22 +00:00
return true ;
return false ;
}
else
{
2010-07-11 02:22:39 +00:00
if ( selfcam = = 1 & & ! r_refdef . externalview )
2006-09-17 00:59:22 +00:00
return true ;
return false ;
}
2004-08-23 00:15:46 +00:00
}
2013-06-23 02:17:02 +00:00
int Cam_TrackNum ( playerview_t * pv )
2004-12-29 03:06:27 +00:00
{
2018-03-25 09:36:14 +00:00
if ( pv - > spectator & & CAM_ISLOCKED ( pv ) )
2015-06-22 11:49:15 +00:00
return pv - > cam_spec_track ;
return - 1 ;
2004-12-29 03:06:27 +00:00
}
2013-06-23 02:17:02 +00:00
void Cam_Unlock ( playerview_t * pv )
2004-08-23 00:15:46 +00:00
{
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state )
2004-08-23 00:15:46 +00:00
{
2005-03-23 22:14:08 +00:00
CL_SendClientCommand ( true , " ptrack " ) ;
2015-06-22 11:49:15 +00:00
pv - > cam_state = CAM_FREECAM ;
2013-06-23 02:17:02 +00:00
pv - > viewentity = ( cls . demoplayback ) ? 0 : ( pv - > playernum + 1 ) ; //free floating
2016-11-20 20:52:41 +00:00
SCR_CenterPrint ( pv - cl . playerview , NULL , true ) ;
2004-08-23 00:15:46 +00:00
Sbar_Changed ( ) ;
2015-07-03 02:07:41 +00:00
2020-12-05 04:07:41 +00:00
//flashgrens suck
pv - > cshifts [ CSHIFT_SERVER ] . percent = 0 ;
2015-07-03 02:07:41 +00:00
Skin_FlushPlayers ( ) ;
2004-08-23 00:15:46 +00:00
}
}
2013-06-23 02:17:02 +00:00
void Cam_Lock ( playerview_t * pv , int playernum )
2004-08-23 00:15:46 +00:00
{
2015-06-22 11:49:15 +00:00
pv - > cam_lastviewtime = - 1000 ; //allow the wallcam to re-snap as soon as it can
2004-12-08 04:14:52 +00:00
2005-03-23 22:14:08 +00:00
CL_SendClientCommand ( true , " ptrack %i " , playernum ) ;
2005-02-28 07:16:19 +00:00
2020-12-05 04:07:41 +00:00
if ( pv - > cam_spec_track ! = playernum )
{ //flashgrens suck
pv - > cshifts [ CSHIFT_SERVER ] . percent = 0 ;
}
2013-06-23 02:17:02 +00:00
pv - > cam_spec_track = playernum ;
2015-06-22 11:49:15 +00:00
pv - > cam_state = CAM_PENDING ;
2014-04-24 01:53:01 +00:00
pv - > viewentity = ( cls . demoplayback ) ? 0 : ( pv - > playernum + 1 ) ; //free floating until actually locked
2016-11-20 20:52:41 +00:00
SCR_CenterPrint ( pv - cl . playerview , NULL , true ) ;
2013-06-23 02:17:02 +00:00
2005-01-23 17:37:35 +00:00
Skin_FlushPlayers ( ) ;
2004-12-08 04:14:52 +00:00
2008-01-09 00:52:31 +00:00
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
2004-12-08 04:14:52 +00:00
{
2013-06-23 02:17:02 +00:00
memcpy ( & pv - > stats , cl . players [ playernum ] . stats , sizeof ( pv - > stats ) ) ;
2015-06-22 11:49:15 +00:00
// pv->cam_state = CAM_;
// pv->viewentity = playernum+1;
/*
pv - > cam_state = cl_chasecam . ival ? CAM_EYECAM : CAM_PENDING ; //instantly lock if the player is valid.
2013-06-23 02:17:02 +00:00
pv - > viewentity = playernum + 1 ;
2015-06-22 11:49:15 +00:00
*/
2015-09-01 04:45:15 +00:00
# ifdef QUAKESTATS
2015-06-12 14:44:50 +00:00
if ( cls . z_ext & Z_EXT_VIEWHEIGHT )
pv - > viewheight = cl . players [ playernum ] . statsf [ STAT_VIEWHEIGHT ] ;
2015-09-01 04:45:15 +00:00
# endif
2004-12-08 04:14:52 +00:00
}
2004-08-23 00:15:46 +00:00
Sbar_Changed ( ) ;
2005-06-14 04:52:10 +00:00
2018-03-04 14:41:16 +00:00
# ifdef QWSKINS
{
int i ;
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
CL_NewTranslation ( i ) ;
}
# endif
2004-08-23 00:15:46 +00:00
}
trace_t Cam_DoTrace ( vec3_t vec1 , vec3_t vec2 )
{
#if 0
memset ( & pmove , 0 , sizeof ( pmove ) ) ;
pmove . numphysent = 1 ;
2009-03-03 01:52:30 +00:00
memset ( & pmove . physents [ 0 ] , 0 , sizeof ( physent_t ) ) ;
2006-05-29 04:50:24 +00:00
VectorClear ( pmove . physents [ 0 ] . origin ) ;
2004-08-23 00:15:46 +00:00
pmove . physents [ 0 ] . model = cl . worldmodel ;
# endif
VectorCopy ( vec1 , pmove . origin ) ;
2013-10-29 17:38:22 +00:00
return PM_PlayerTrace ( pmove . origin , vec2 , MASK_PLAYERSOLID ) ;
2004-08-23 00:15:46 +00:00
}
// Returns distance or 9999 if invalid for some reason
2006-09-17 00:59:22 +00:00
static float Cam_TryFlyby ( vec3_t selforigin , vec3_t playerorigin , vec3_t vec , qboolean checkvis )
2004-08-23 00:15:46 +00:00
{
vec3_t v ;
trace_t trace ;
float len ;
2014-01-13 02:42:25 +00:00
pmove . player_mins [ 0 ] = pmove . player_mins [ 1 ] = - 16 ;
pmove . player_mins [ 2 ] = - 24 ;
pmove . player_maxs [ 0 ] = pmove . player_maxs [ 1 ] = 16 ;
pmove . player_maxs [ 2 ] = 32 ;
2004-11-17 18:10:06 +00:00
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
VectorAngles ( vec , NULL , v , true ) ;
2004-08-23 00:15:46 +00:00
VectorCopy ( v , pmove . angles ) ;
VectorNormalize ( vec ) ;
2006-09-17 00:59:22 +00:00
VectorMA ( playerorigin , 800 , vec , v ) ;
2004-08-23 00:15:46 +00:00
// v is endpos
// fake a player move
2006-09-17 00:59:22 +00:00
trace = Cam_DoTrace ( playerorigin , v ) ;
2004-08-23 00:15:46 +00:00
if ( /*trace.inopen ||*/ trace . inwater )
return 9999 ;
VectorCopy ( trace . endpos , vec ) ;
2006-09-17 00:59:22 +00:00
VectorSubtract ( trace . endpos , playerorigin , v ) ;
2004-08-23 00:15:46 +00:00
len = sqrt ( v [ 0 ] * v [ 0 ] + v [ 1 ] * v [ 1 ] + v [ 2 ] * v [ 2 ] ) ;
if ( len < 32 | | len > 800 )
return 9999 ;
if ( checkvis )
{
2006-09-17 00:59:22 +00:00
VectorSubtract ( trace . endpos , selforigin , v ) ;
2004-08-23 00:15:46 +00:00
len = sqrt ( v [ 0 ] * v [ 0 ] + v [ 1 ] * v [ 1 ] + v [ 2 ] * v [ 2 ] ) ;
2006-09-17 00:59:22 +00:00
trace = Cam_DoTrace ( selforigin , vec ) ;
2004-08-23 00:15:46 +00:00
if ( trace . fraction ! = 1 | | trace . inwater )
return 9999 ;
}
return len ;
}
// Is player visible?
2006-09-17 00:59:22 +00:00
static qboolean Cam_IsVisible ( vec3_t playerorigin , vec3_t vec )
2004-08-23 00:15:46 +00:00
{
trace_t trace ;
vec3_t v ;
float d ;
2018-03-25 09:36:14 +00:00
VectorClear ( pmove . player_mins ) ;
VectorClear ( pmove . player_maxs ) ;
2006-09-17 00:59:22 +00:00
trace = Cam_DoTrace ( playerorigin , vec ) ;
2004-08-23 00:15:46 +00:00
if ( trace . fraction ! = 1 | | /*trace.inopen ||*/ trace . inwater )
return false ;
// check distance, don't let the player get too far away or too close
2006-09-17 00:59:22 +00:00
VectorSubtract ( playerorigin , vec , v ) ;
2004-08-23 00:15:46 +00:00
d = vlen ( v ) ;
if ( d < 16 )
return false ;
return true ;
}
2013-06-23 02:17:02 +00:00
static qboolean InitFlyby ( playerview_t * pv , vec3_t selforigin , vec3_t playerorigin , vec3_t playerviewangles , int checkvis )
2004-08-23 00:15:46 +00:00
{
2014-11-01 09:09:58 +00:00
vec3_t dirs [ ] = {
{ 1 , 1 , 1 } ,
{ 1 , - 1 , 1 } ,
{ 1 , 1 , 0 } ,
{ 1 , - 1 , 1 } ,
{ 1 , 0 , 1 } ,
{ 1 , 0 , - 1 } ,
{ - 1 , 1 , 1 } ,
{ - 1 , - 1 , 1 } ,
{ - 1 , 0 , 0 } ,
{ 1 , 0 , 0 } ,
{ 0 , 0 , - 1 } ,
{ 0 , 0 , 1 }
} ;
int dir ;
float f , max ;
vec3_t vec , vec2 ;
2004-08-23 00:15:46 +00:00
vec3_t forward , right , up ;
2006-09-17 00:59:22 +00:00
VectorCopy ( playerviewangles , vec ) ;
2014-11-01 09:09:58 +00:00
vec [ 0 ] = 0 ;
2004-08-23 00:15:46 +00:00
AngleVectors ( vec , forward , right , up ) ;
// for (i = 0; i < 3; i++)
// forward[i] *= 3;
2014-11-01 09:09:58 +00:00
max = 1000 ;
for ( dir = 0 ; dir < sizeof ( dirs ) / sizeof ( dirs [ 0 ] ) ; dir + + )
2004-08-23 00:15:46 +00:00
{
2014-11-01 09:09:58 +00:00
VectorScale ( forward , dirs [ dir ] [ 0 ] , vec2 ) ;
VectorMA ( vec2 , dirs [ dir ] [ 1 ] , right , vec2 ) ;
VectorMA ( vec2 , dirs [ dir ] [ 2 ] , up , vec2 ) ;
if ( ( f = Cam_TryFlyby ( selforigin , playerorigin , vec2 , checkvis ) ) < max )
{
max = f ;
VectorCopy ( vec2 , vec ) ;
}
}
2004-08-23 00:15:46 +00:00
// ack, can't find him
2014-11-01 09:09:58 +00:00
if ( max > = 1000 )
2004-08-23 00:15:46 +00:00
{
// Cam_Unlock();
return false ;
}
2004-10-04 07:25:47 +00:00
2015-06-22 11:49:15 +00:00
pv - > cam_state = CAM_WALLCAM ;
2014-10-19 03:40:27 +00:00
pv - > viewentity = pv - > playernum + 1 ; //pv->cam_spec_track+1;
2013-06-23 02:17:02 +00:00
VectorCopy ( vec , pv - > cam_desired_position ) ;
2004-08-23 00:15:46 +00:00
return true ;
}
2013-06-23 02:17:02 +00:00
static void Cam_CheckHighTarget ( playerview_t * pv )
2004-08-23 00:15:46 +00:00
{
2015-06-12 14:44:50 +00:00
int j ;
2013-06-23 02:17:02 +00:00
playerview_t * spv ;
2004-08-23 00:15:46 +00:00
2015-06-12 14:44:50 +00:00
j = CL_AutoTrack_Choose ( pv - cl . playerview ) ;
2004-08-23 00:15:46 +00:00
if ( j > = 0 )
{
2015-06-22 11:49:15 +00:00
if ( pv - > cam_spec_track ! = j | | pv - > cam_state = = CAM_FREECAM )
2009-05-24 10:11:17 +00:00
{
2017-07-10 15:40:42 +00:00
# ifdef QUAKEHUD
2015-06-14 01:28:01 +00:00
if ( cl . teamplay )
Stats_Message ( " Now tracking: \n %s \n %s " , cl . players [ j ] . name , cl . players [ j ] . team ) ;
else
Stats_Message ( " Now tracking: \n %s " , cl . players [ j ] . name ) ;
2017-07-10 15:40:42 +00:00
# endif
2013-06-23 02:17:02 +00:00
Cam_Lock ( pv , j ) ;
//un-lock any higher seats watching our new target. this keeps things ordered.
for ( spv = pv + 1 ; spv > = cl . playerview & & spv < & cl . playerview [ cl . splitclients ] ; spv + + )
2009-05-24 10:11:17 +00:00
{
2013-06-23 02:17:02 +00:00
if ( Cam_TrackNum ( spv ) = = j )
2015-06-22 11:49:15 +00:00
spv - > cam_state = CAM_FREECAM ;
2009-05-24 10:11:17 +00:00
}
}
2004-08-23 00:15:46 +00:00
}
else
2013-06-23 02:17:02 +00:00
Cam_Unlock ( pv ) ;
2004-08-23 00:15:46 +00:00
}
2005-04-16 16:21:27 +00:00
2013-06-23 02:17:02 +00:00
void Cam_SelfTrack ( playerview_t * pv )
2006-09-17 00:59:22 +00:00
{
vec3_t vec ;
2014-10-05 20:04:11 +00:00
if ( ! cl . worldmodel | | cl . worldmodel - > loadstate ! = MLS_LOADED )
2006-09-17 00:59:22 +00:00
return ;
if ( selfcam = = 1 )
{ //view-from-eyes
}
else
{
if ( selfcam = = 2 )
{ //fixme:
vec3_t forward , right , up ;
trace_t tr ;
AngleVectors ( r_refdef . viewangles , forward , right , up ) ;
2013-06-23 02:17:02 +00:00
VectorMA ( pv - > simorg , - 128 , forward , pv - > cam_desired_position ) ;
tr = Cam_DoTrace ( pv - > simorg , pv - > cam_desired_position ) ;
VectorCopy ( tr . endpos , pv - > cam_desired_position ) ;
2006-09-17 00:59:22 +00:00
}
else
{ //view from a random wall
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_WALLCAM | | ! Cam_IsVisible ( pv - > simorg , pv - > cam_desired_position ) )
2006-09-17 00:59:22 +00:00
{
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_WALLCAM | | realtime - pv - > cam_lastviewtime > 0.1 )
2006-09-17 00:59:22 +00:00
{
2013-06-23 02:17:02 +00:00
if ( ! InitFlyby ( pv , pv - > cam_desired_position , pv - > simorg , pv - > simangles , true ) )
InitFlyby ( pv , pv - > cam_desired_position , pv - > simorg , pv - > simangles , false ) ;
pv - > cam_lastviewtime = realtime ;
2006-09-17 00:59:22 +00:00
}
}
else
{
2013-06-23 02:17:02 +00:00
pv - > cam_lastviewtime = realtime ;
2006-09-17 00:59:22 +00:00
}
//tracking failed.
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_WALLCAM )
2006-09-17 00:59:22 +00:00
return ;
}
// move there locally immediately
2013-06-23 02:17:02 +00:00
VectorCopy ( pv - > cam_desired_position , r_refdef . vieworg ) ;
2006-09-17 00:59:22 +00:00
2013-06-23 02:17:02 +00:00
VectorSubtract ( pv - > simorg , pv - > cam_desired_position , vec ) ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
VectorAngles ( vec , NULL , r_refdef . viewangles , false ) ;
2006-09-17 00:59:22 +00:00
}
}
2015-06-22 11:49:15 +00:00
//player entity became visible, lock on to them (now that we know where they are etc)
void Cam_NowLocked ( playerview_t * pv )
{
pv - > cam_lastviewtime = realtime ;
if ( ! cl_chasecam . ival )
{
if ( pv - > cam_state ! = CAM_WALLCAM | | ! Cam_IsVisible ( pv - > simorg , pv - > cam_desired_position ) )
{
if ( pv - > cam_state ! = CAM_WALLCAM | | realtime - pv - > cam_lastviewtime > 0.1 )
{
if ( ! InitFlyby ( pv , pv - > cam_desired_position , pv - > simorg , pv - > simangles , true ) )
InitFlyby ( pv , pv - > cam_desired_position , pv - > simorg , pv - > simangles , false ) ;
}
}
}
}
2004-08-23 00:15:46 +00:00
// ZOID
//
// Take over the user controls and track a player.
// We find a nice position to watch the player and move there
2013-06-23 02:17:02 +00:00
void Cam_Track ( playerview_t * pv , usercmd_t * cmd )
2004-08-23 00:15:46 +00:00
{
player_state_t * player , * self ;
2013-03-12 22:53:23 +00:00
inframe_t * frame ;
2004-08-23 00:15:46 +00:00
vec3_t vec ;
float len ;
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator | | ! cl . worldmodel ) //can happen when the server changes level
2004-08-23 00:15:46 +00:00
return ;
2015-06-22 11:49:15 +00:00
if ( autotrackmode ! = TM_USER & & pv - > cam_state = = CAM_FREECAM )
2013-06-23 02:17:02 +00:00
Cam_CheckHighTarget ( pv ) ;
2004-08-23 00:15:46 +00:00
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state = = CAM_FREECAM | | cls . state ! = ca_active | | cl . worldmodel - > loadstate ! = MLS_LOADED )
2004-08-23 00:15:46 +00:00
return ;
2015-06-22 11:49:15 +00:00
if ( CAM_ISLOCKED ( pv ) & & ( ! cl . players [ pv - > cam_spec_track ] . name [ 0 ] | | cl . players [ pv - > cam_spec_track ] . spectator ) )
2004-08-23 00:15:46 +00:00
{
2015-06-22 11:49:15 +00:00
pv - > cam_state = CAM_FREECAM ;
2015-06-12 14:44:50 +00:00
if ( autotrackmode ! = TM_USER )
2013-06-23 02:17:02 +00:00
Cam_CheckHighTarget ( pv ) ;
2004-08-23 00:15:46 +00:00
else
2013-06-23 02:17:02 +00:00
Cam_Unlock ( pv ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2013-03-12 22:53:23 +00:00
frame = & cl . inframes [ cl . validsequence & UPDATE_MASK ] ;
2013-06-23 02:17:02 +00:00
player = frame - > playerstate + pv - > cam_spec_track ;
2018-03-25 09:36:14 +00:00
if ( ! cmd )
{ //this is our fancy force-wallcam mode.
if ( pv - > cam_state ! = CAM_WALLCAM | | ! Cam_IsVisible ( player - > origin , pv - > cam_desired_position ) )
{
if ( ! InitFlyby ( pv , pv - > cam_desired_position , player - > origin , player - > viewangles , true ) )
InitFlyby ( pv , pv - > cam_desired_position , player - > origin , player - > viewangles , false ) ;
}
return ;
}
2013-06-23 02:17:02 +00:00
self = frame - > playerstate + pv - > playernum ;
2004-08-23 00:15:46 +00:00
2015-06-22 11:49:15 +00:00
if ( ! cl_chasecam . value & & ( pv - > cam_state ! = CAM_WALLCAM | | ! Cam_IsVisible ( player - > origin , pv - > cam_desired_position ) ) )
2004-08-23 00:15:46 +00:00
{
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_WALLCAM | | realtime - pv - > cam_lastviewtime > 0.1 )
2004-08-23 00:15:46 +00:00
{
2013-06-23 02:17:02 +00:00
if ( ! InitFlyby ( pv , self - > origin , player - > origin , player - > viewangles , true ) )
InitFlyby ( pv , self - > origin , player - > origin , player - > viewangles , false ) ;
pv - > cam_lastviewtime = realtime ;
2004-08-23 00:15:46 +00:00
}
}
2015-06-22 11:49:15 +00:00
else if ( cl_chasecam . value & & pv - > cam_state = = CAM_WALLCAM )
pv - > cam_state = CAM_PENDING ;
2004-08-23 00:15:46 +00:00
else
2005-04-16 16:21:27 +00:00
{
2013-06-23 02:17:02 +00:00
pv - > cam_lastviewtime = realtime ;
2005-04-16 16:21:27 +00:00
}
//tracking failed.
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state = = CAM_FREECAM | | pv - > cam_state = = CAM_PENDING )
2004-08-23 00:15:46 +00:00
return ;
2005-04-16 16:21:27 +00:00
2018-03-25 09:36:14 +00:00
if ( cl_chasecam . value )
2004-08-23 00:15:46 +00:00
{
2013-10-08 14:28:11 +00:00
float * neworg ;
// float *newang;
if ( pv - > nolocalplayer )
neworg = cl . lerpents [ pv - > viewentity ] . origin ;
else
neworg = player - > origin ;
2018-03-25 09:36:14 +00:00
pv - > cam_lastviewtime = realtime ;
2005-04-16 16:21:27 +00:00
2013-10-08 14:28:11 +00:00
// VectorCopy(newang, pv->viewangles);
if ( memcmp ( neworg , & self - > origin , sizeof ( vec3_t ) ) ! = 0 )
2004-08-23 00:15:46 +00:00
{
2007-07-23 12:04:26 +00:00
if ( ! cls . demoplayback )
{
MSG_WriteByte ( & cls . netchan . message , clc_tmove ) ;
2013-10-08 14:28:11 +00:00
MSG_WriteCoord ( & cls . netchan . message , neworg [ 0 ] ) ;
MSG_WriteCoord ( & cls . netchan . message , neworg [ 1 ] ) ;
MSG_WriteCoord ( & cls . netchan . message , neworg [ 2 ] ) ;
2007-07-23 12:04:26 +00:00
}
2004-08-23 00:15:46 +00:00
// move there locally immediately
2013-10-08 14:28:11 +00:00
VectorCopy ( neworg , self - > origin ) ;
2004-08-23 00:15:46 +00:00
}
self - > weaponframe = player - > weaponframe ;
2014-10-19 03:40:27 +00:00
VectorCopy ( player - > viewangles , pv - > viewangles ) ;
2005-04-16 16:21:27 +00:00
return ;
}
// Ok, move to our desired position and set our angles to view
// the player
2013-06-23 02:17:02 +00:00
VectorSubtract ( pv - > cam_desired_position , self - > origin , vec ) ;
2005-04-16 16:21:27 +00:00
len = vlen ( vec ) ;
cmd - > forwardmove = cmd - > sidemove = cmd - > upmove = 0 ;
if ( len > 16 )
{ // close enough?
MSG_WriteByte ( & cls . netchan . message , clc_tmove ) ;
2013-06-23 02:17:02 +00:00
MSG_WriteCoord ( & cls . netchan . message , pv - > cam_desired_position [ 0 ] ) ;
MSG_WriteCoord ( & cls . netchan . message , pv - > cam_desired_position [ 1 ] ) ;
MSG_WriteCoord ( & cls . netchan . message , pv - > cam_desired_position [ 2 ] ) ;
2004-08-23 00:15:46 +00:00
}
2005-04-16 16:21:27 +00:00
// move there locally immediately
2013-06-23 02:17:02 +00:00
VectorCopy ( pv - > cam_desired_position , self - > origin ) ;
2004-08-23 00:15:46 +00:00
2015-06-22 11:49:15 +00:00
// VectorSubtract(player->origin, pv->cam_desired_position, vec);
// VectorAngles(vec, NULL, pv->viewangles);
// pv->viewangles[0] = -pv->viewangles[0];
2004-08-23 00:15:46 +00:00
}
2015-06-22 11:49:15 +00:00
void Cam_SetModAutoTrack ( int userid )
2008-01-30 02:32:00 +00:00
{ //this is a hint from the server about who to track
2015-06-12 14:44:50 +00:00
int slot ;
2015-06-14 01:28:01 +00:00
cl . autotrack_hint = - 1 ;
2015-06-12 14:44:50 +00:00
for ( slot = 0 ; slot < cl . allocated_client_slots ; slot + + )
{
if ( cl . players [ slot ] . userid = = userid )
{
2015-06-14 01:28:01 +00:00
cl . autotrack_hint = slot ;
2015-06-12 14:44:50 +00:00
return ;
}
}
Con_Printf ( " //at: invalid userid \n " ) ;
2008-01-30 02:32:00 +00:00
}
2020-02-11 18:06:10 +00:00
/*static void Cam_TrackCrosshairedPlayer(playerview_t *pv)
2005-03-28 00:11:59 +00:00
{
2013-03-12 22:53:23 +00:00
inframe_t * frame ;
2005-03-28 00:11:59 +00:00
player_state_t * player ;
int i ;
2005-04-16 16:21:27 +00:00
float dot = 0.1 , bestdot = 0 ;
2005-03-28 00:11:59 +00:00
int best = - 1 ;
vec3_t selforg ;
vec3_t dir ;
2013-03-12 22:53:23 +00:00
frame = & cl . inframes [ cl . validsequence & UPDATE_MASK ] ;
2013-06-23 02:17:02 +00:00
player = frame - > playerstate + pv - > playernum ;
2005-03-28 00:11:59 +00:00
VectorCopy ( player - > origin , selforg ) ;
2013-10-29 17:38:22 +00:00
for ( i = 0 ; i < cl . allocated_client_slots ; i + + )
2005-03-28 00:11:59 +00:00
{
player = frame - > playerstate + i ;
VectorSubtract ( player - > origin , selforg , dir ) ;
VectorNormalize ( dir ) ;
dot = DotProduct ( vpn , dir ) ;
if ( dot > bestdot )
{
bestdot = dot ;
best = i ;
}
}
2015-03-03 00:14:43 +00:00
// Con_Printf("Track %i? %f\n", best, bestdot);
2020-02-11 18:06:10 +00:00
if ( best > .707 ) //did we actually get someone?
2005-03-28 00:11:59 +00:00
{
2013-06-23 02:17:02 +00:00
Cam_Lock ( pv , best ) ;
2005-03-28 00:11:59 +00:00
}
2020-02-11 18:06:10 +00:00
} */
2005-03-28 00:11:59 +00:00
2013-06-23 02:17:02 +00:00
void Cam_FinishMove ( playerview_t * pv , usercmd_t * cmd )
2004-08-23 00:15:46 +00:00
{
int i ;
player_info_t * s ;
int end ;
2013-03-12 22:13:26 +00:00
extern cvar_t cl_demospeed , cl_splitscreen ;
2004-08-23 00:15:46 +00:00
if ( cls . state ! = ca_active )
return ;
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator & & ( cls . demoplayback ! = DPB_MVD & & cls . demoplayback ! = DPB_EZTV ) ) // only in spectator mode
2004-08-23 00:15:46 +00:00
return ;
2013-03-12 22:13:26 +00:00
if ( cls . demoplayback = = DPB_MVD | | cls . demoplayback = = DPB_EZTV )
{
int nb ;
nb = ( cmd - > sidemove < 0 ) ? 4 : 0 ;
nb | = ( cmd - > sidemove > 0 ) ? 8 : 0 ;
nb | = ( cmd - > forwardmove < 0 ) ? 16 : 0 ;
nb | = ( cmd - > forwardmove > 0 ) ? 32 : 0 ;
nb | = ( cmd - > upmove < 0 ) ? 64 : 0 ;
nb | = ( cmd - > upmove > 0 ) ? 128 : 0 ;
2013-06-23 02:17:02 +00:00
if ( Cam_TrackNum ( pv ) > = 0 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
{
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & 4 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Cvar_SetValue ( & cl_demospeed , max ( cl_demospeed . value - 0.1 , 0 ) ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & 8 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Cvar_SetValue ( & cl_demospeed , min ( cl_demospeed . value + 0.1 , 10 ) ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & ( 4 | 8 ) )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Con_Printf ( " playback speed: %g%% \n " , cl_demospeed . value * 100 ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & 16 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Cbuf_AddText ( " demo_jump +10 " , RESTRICT_LOCAL ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & 32 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Cbuf_AddText ( " demo_jump -10 " , RESTRICT_LOCAL ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & ( 4 | 8 ) )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Con_Printf ( " playback speed: %g%% \n " , cl_demospeed . value * 100 ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & 64 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Cvar_SetValue ( & cl_splitscreen , max ( cl_splitscreen . ival - 1 , 0 ) ) ;
2013-06-23 02:17:02 +00:00
if ( nb & ( nb ^ pv - > cam_oldbuttons ) & 128 )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Cvar_SetValue ( & cl_splitscreen , min ( cl_splitscreen . ival + 1 , MAX_SPLITS - 1 ) ) ;
}
2013-06-23 02:17:02 +00:00
pv - > cam_oldbuttons = ( pv - > cam_oldbuttons & 3 ) | ( nb & ~ 3 ) ;
2013-03-12 22:13:26 +00:00
if ( cmd - > impulse )
{
int pl = cmd - > impulse ;
2015-04-14 23:12:17 +00:00
# if 1
do
{
Cam_Lock ( pv , Cam_FindSortedPlayer ( pl ) ) ;
pv + + ;
pl + + ;
} while ( pv > = & cl . playerview [ 0 ] & & pv < & cl . playerview [ cl . splitclients ] ) ;
# else
2013-03-12 22:13:26 +00:00
for ( i = 0 ; ; i + + )
{
if ( i = = MAX_CLIENTS )
{
if ( pl = = cmd - > impulse )
break ;
i = 0 ;
}
s = & cl . players [ i ] ;
if ( s - > name [ 0 ] & & ! s - > spectator )
{
pl - - ;
if ( ! pl )
{
2013-06-23 02:17:02 +00:00
Cam_Lock ( pv , i ) ;
if ( pv > = & cl . playerview [ 0 ] & & pv < & cl . playerview [ cl . splitclients ] )
{
2013-03-12 22:13:26 +00:00
pl = 1 ;
2013-06-23 02:17:02 +00:00
pv + + ;
}
2013-03-12 22:13:26 +00:00
else
break ;
}
}
}
2015-04-14 23:12:17 +00:00
# endif
2013-03-12 22:13:26 +00:00
return ;
}
}
2004-08-23 00:15:46 +00:00
if ( cmd - > buttons & BUTTON_ATTACK )
{
2013-06-23 02:17:02 +00:00
if ( ! ( pv - > cam_oldbuttons & BUTTON_ATTACK ) )
2004-08-23 00:15:46 +00:00
{
2013-06-23 02:17:02 +00:00
pv - > cam_oldbuttons | = BUTTON_ATTACK ;
2004-08-23 00:15:46 +00:00
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_FREECAM )
2004-08-23 00:15:46 +00:00
{
2013-06-23 02:17:02 +00:00
Cam_Unlock ( pv ) ;
VectorCopy ( pv - > viewangles , cmd - > angles ) ;
2015-06-14 01:28:01 +00:00
autotrackmode = TM_USER ;
2004-08-23 00:15:46 +00:00
return ;
}
}
else
return ;
}
else
{
2013-06-23 02:17:02 +00:00
pv - > cam_oldbuttons & = ~ BUTTON_ATTACK ;
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state = = CAM_FREECAM & & autotrackmode = = TM_USER )
2005-03-28 00:11:59 +00:00
{
2020-02-11 18:06:10 +00:00
// if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP))
// Cam_TrackCrosshairedPlayer(pv);
2013-06-23 02:17:02 +00:00
pv - > cam_oldbuttons = ( pv - > cam_oldbuttons & ~ BUTTON_JUMP ) | ( cmd - > buttons & BUTTON_JUMP ) ;
2004-08-23 00:15:46 +00:00
return ;
2005-03-28 00:11:59 +00:00
}
2004-08-23 00:15:46 +00:00
}
2015-06-22 11:49:15 +00:00
if ( autotrackmode ! = TM_USER )
2004-08-23 00:15:46 +00:00
{
2015-06-12 14:44:50 +00:00
if ( ( cmd - > buttons & BUTTON_JUMP ) & & ! ( pv - > cam_oldbuttons & BUTTON_JUMP ) )
autotrackmode = TM_USER ;
else
{
Cam_CheckHighTarget ( pv ) ;
return ;
}
2004-08-23 00:15:46 +00:00
}
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_FREECAM )
2004-08-23 00:15:46 +00:00
{
2013-06-23 02:17:02 +00:00
if ( ( cmd - > buttons & BUTTON_JUMP ) & & ( pv - > cam_oldbuttons & BUTTON_JUMP ) )
2004-08-23 00:15:46 +00:00
return ; // don't pogo stick
if ( ! ( cmd - > buttons & BUTTON_JUMP ) )
{
2013-06-23 02:17:02 +00:00
pv - > cam_oldbuttons & = ~ BUTTON_JUMP ;
2004-08-23 00:15:46 +00:00
return ;
}
2013-06-23 02:17:02 +00:00
pv - > cam_oldbuttons | = BUTTON_JUMP ; // don't jump again until released
2004-08-23 00:15:46 +00:00
}
// Con_Printf("Selecting track target...\n");
2015-06-22 11:49:15 +00:00
if ( pv - > cam_state ! = CAM_FREECAM )
end = ( pv - > cam_spec_track + 1 ) % MAX_CLIENTS ;
2004-08-23 00:15:46 +00:00
else
2013-06-23 02:17:02 +00:00
end = pv - > cam_spec_track ;
2016-12-13 11:50:15 +00:00
end = max ( 0 , end ) % cl . allocated_client_slots ;
2004-08-23 00:15:46 +00:00
i = end ;
do
{
s = & cl . players [ i ] ;
2015-04-14 23:12:17 +00:00
//players with userid 0 are typically bots.
//trying to spectate such bots just does not work (we have no idea which entity slot the bot is actually using, so don't try to track them).
if ( s - > name [ 0 ] & & ! s - > spectator & & s - > userid )
2004-08-23 00:15:46 +00:00
{
2013-06-23 02:17:02 +00:00
Cam_Lock ( pv , i ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2013-12-02 14:30:30 +00:00
i = ( i + 1 ) % cl . allocated_client_slots ;
2004-08-23 00:15:46 +00:00
} while ( i ! = end ) ;
// stay on same guy?
2013-06-23 02:17:02 +00:00
i = pv - > cam_spec_track ;
2004-08-23 00:15:46 +00:00
s = & cl . players [ i ] ;
2015-04-14 23:12:17 +00:00
if ( s - > name [ 0 ] & & ! s - > spectator & & s - > userid )
2004-08-23 00:15:46 +00:00
{
2013-06-23 02:17:02 +00:00
Cam_Lock ( pv , i ) ;
2004-08-23 00:15:46 +00:00
return ;
}
Con_Printf ( " No target found ... \n " ) ;
2015-06-22 11:49:15 +00:00
pv - > cam_state = CAM_FREECAM ;
2004-08-23 00:15:46 +00:00
}
void Cam_Reset ( void )
{
2018-03-25 09:36:14 +00:00
unsigned int pnum ;
2004-08-23 00:15:46 +00:00
for ( pnum = 0 ; pnum < MAX_SPLITS ; pnum + + )
{
2013-06-23 02:17:02 +00:00
playerview_t * pv = & cl . playerview [ pnum ] ;
2015-06-22 11:49:15 +00:00
pv - > cam_state = CAM_FREECAM ;
2013-06-23 02:17:02 +00:00
pv - > cam_spec_track = 0 ;
2004-08-23 00:15:46 +00:00
}
}
2015-04-14 23:12:17 +00:00
static int QDECL Cam_SortPlayers ( const void * p1 , const void * p2 )
{
const player_info_t * a = * ( player_info_t * * ) p1 ;
const player_info_t * b = * ( player_info_t * * ) p2 ;
if ( ! * a - > team )
return * b - > team ;
if ( ! * b - > team )
return - * a - > team ;
// if (a->spectator || b->spectator)
// return a->spectator - b->spectator;
return Q_strcasecmp ( a - > team , b - > team ) ;
}
static int Cam_FindSortedPlayer ( int number )
{
player_info_t * playerlist [ MAX_CLIENTS ] , * s ;
int i ;
int slots ;
number - - ;
for ( slots = 0 , i = 0 ; i < cl . allocated_client_slots ; i + + )
{
s = & cl . players [ i ] ;
if ( s - > name [ 0 ] & & ! s - > spectator )
playerlist [ slots + + ] = s ;
}
if ( ! slots )
return 0 ;
// if (number > slot)
// return cl.allocated_client_slots; //error
qsort ( playerlist , slots , sizeof ( playerlist [ 0 ] ) , Cam_SortPlayers ) ;
return playerlist [ number % slots ] - cl . players ;
}
2013-06-23 02:17:02 +00:00
void Cam_TrackPlayer ( int seat , char * cmdname , char * plrarg )
2006-05-18 00:48:43 +00:00
{
2013-06-23 02:17:02 +00:00
playerview_t * pv = & cl . playerview [ seat ] ;
2015-06-12 14:44:50 +00:00
int slot ;
2006-05-18 00:48:43 +00:00
player_info_t * s ;
2015-04-14 23:12:17 +00:00
char * e ;
2006-05-18 00:48:43 +00:00
2013-06-23 02:17:02 +00:00
if ( seat > = MAX_SPLITS )
2006-05-18 01:19:19 +00:00
return ;
2006-05-18 00:48:43 +00:00
if ( cls . state < = ca_connected )
{
Con_Printf ( " Not connected. \n " ) ;
return ;
}
2017-05-28 15:42:32 +00:00
if ( ! pv - > spectator )
2006-05-18 00:48:43 +00:00
{
Con_Printf ( " Not spectating. \n " ) ;
return ;
}
if ( ! Q_strcasecmp ( plrarg , " off " ) )
{
2013-06-23 02:17:02 +00:00
Cam_Unlock ( pv ) ;
2006-05-18 00:48:43 +00:00
return ;
}
2015-04-14 23:12:17 +00:00
if ( * plrarg = = ' # ' & & ( slot = strtoul ( plrarg + 1 , & e , 10 ) ) & & ! * e )
slot = Cam_FindSortedPlayer ( slot ) ;
else
2006-05-18 00:48:43 +00:00
{
2015-04-14 23:12:17 +00:00
// search nicks first
for ( slot = 0 ; slot < cl . allocated_client_slots ; slot + + )
{
s = & cl . players [ slot ] ;
if ( s - > name [ 0 ] & & ! s - > spectator & & ! Q_strcasecmp ( s - > name , plrarg ) )
break ;
}
2006-05-18 00:48:43 +00:00
}
2013-08-27 13:18:09 +00:00
if ( slot = = cl . allocated_client_slots )
2006-05-18 00:48:43 +00:00
{
// didn't find nick, so search userids
int userid ;
char * c ;
// check if given arg is in fact a number
c = plrarg ;
while ( * c )
{
2012-11-27 03:23:19 +00:00
if ( * c < ' 0 ' | | * c > ' 9 ' )
2006-05-18 00:48:43 +00:00
{
Con_Printf ( " Couldn't find nick %s \n " , plrarg ) ;
return ;
}
c + + ;
}
userid = atoi ( plrarg ) ;
2013-08-27 13:18:09 +00:00
for ( slot = 0 ; slot < cl . allocated_client_slots ; slot + + )
2006-05-18 00:48:43 +00:00
{
s = & cl . players [ slot ] ;
if ( s - > name [ 0 ] & & ! s - > spectator & & s - > userid = = userid )
break ;
}
2013-08-27 13:18:09 +00:00
if ( slot = = cl . allocated_client_slots )
2006-05-18 00:48:43 +00:00
{
Con_Printf ( " Couldn't find userid %i \n " , userid ) ;
return ;
}
}
2013-06-23 02:17:02 +00:00
Cam_Lock ( pv , slot ) ;
2006-05-18 00:48:43 +00:00
}
void Cam_Track_f ( void )
{
int i , j ;
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Usage: %s userid|nick|off \n " , Cmd_Argv ( 0 ) ) ;
return ;
}
i = 1 ;
j = Cmd_Argc ( ) - 1 ;
if ( j > MAX_SPLITS )
j = MAX_SPLITS ;
while ( j > 0 )
{
Cam_TrackPlayer ( i - 1 , Cmd_Argv ( 0 ) , Cmd_Argv ( i ) ) ;
i + + ;
j - - ;
}
}
void Cam_Track1_f ( void )
{
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Usage: %s userid|nick|off \n " , Cmd_Argv ( 0 ) ) ;
return ;
}
Cam_TrackPlayer ( 0 , Cmd_Argv ( 0 ) , Cmd_Argv ( 1 ) ) ;
}
void Cam_Track2_f ( void )
{
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Usage: %s userid|nick|off \n " , Cmd_Argv ( 0 ) ) ;
return ;
}
Cam_TrackPlayer ( 1 , Cmd_Argv ( 0 ) , Cmd_Argv ( 1 ) ) ;
}
void Cam_Track3_f ( void )
{
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Usage: %s userid|nick|off \n " , Cmd_Argv ( 0 ) ) ;
return ;
}
Cam_TrackPlayer ( 2 , Cmd_Argv ( 0 ) , Cmd_Argv ( 1 ) ) ;
}
void Cam_Track4_f ( void )
{
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Usage: %s userid|nick|off \n " , Cmd_Argv ( 0 ) ) ;
return ;
}
Cam_TrackPlayer ( 3 , Cmd_Argv ( 0 ) , Cmd_Argv ( 1 ) ) ;
}
2004-08-23 00:15:46 +00:00
void CL_InitCam ( void )
{
2015-06-12 14:44:50 +00:00
Cvar_Register ( & cl_autotrack , cl_spectatorgroup ) ;
2016-01-18 05:22:07 +00:00
Cvar_Register ( & cl_autotrack_team , cl_spectatorgroup ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & cl_hightrack , cl_spectatorgroup ) ;
Cvar_Register ( & cl_chasecam , cl_spectatorgroup ) ;
// Cvar_Register (&cl_camera_maxpitch, cl_spectatorgroup);
// Cvar_Register (&cl_camera_maxyaw, cl_spectatorgroup);
2006-09-17 00:59:22 +00:00
// Cvar_Register (&cl_selfcam, cl_spectatorgroup);
2006-05-18 00:48:43 +00:00
2015-06-12 14:44:50 +00:00
Cmd_AddCommand ( " autotrack " , Cam_AutoTrack_f ) ; //reset it, if they jumped or something.
2006-05-18 00:48:43 +00:00
Cmd_AddCommand ( " track " , Cam_Track_f ) ;
Cmd_AddCommand ( " track1 " , Cam_Track1_f ) ;
Cmd_AddCommand ( " track2 " , Cam_Track2_f ) ;
Cmd_AddCommand ( " track3 " , Cam_Track3_f ) ;
Cmd_AddCommand ( " track4 " , Cam_Track4_f ) ;
2004-08-23 00:15:46 +00:00
}