mirror of
https://github.com/FWGS/hlsdk-xash3d
synced 2024-11-21 17:36:18 +01:00
Port spectator changes from HLSDK 2.4.
This commit is contained in:
parent
011f1afeb6
commit
955f7ad436
@ -70,6 +70,7 @@ SRCS+=./in_camera.cpp
|
||||
SRCS+=./input.cpp
|
||||
SRCS+=./input_goldsource.cpp
|
||||
SRCS+=./input_mouse.cpp
|
||||
SRCS+=./interpolation.cpp
|
||||
#SRCS+=./inputw32.cpp
|
||||
SRCS+=./menu.cpp
|
||||
SRCS+=./message.cpp
|
||||
|
@ -107,6 +107,7 @@ set (CLDLL_SOURCES
|
||||
input_goldsource.cpp
|
||||
input_mouse.cpp
|
||||
input_xash3d.cpp
|
||||
interpolation.cpp
|
||||
menu.cpp
|
||||
message.cpp
|
||||
parsemsg.cpp
|
||||
|
@ -52,6 +52,7 @@ set SOURCES=../dlls/crossbow.cpp ^
|
||||
input_goldsource.cpp ^
|
||||
input_mouse.cpp ^
|
||||
input_xash3d.cpp ^
|
||||
interpolation.cpp ^
|
||||
menu.cpp ^
|
||||
message.cpp ^
|
||||
parsemsg.cpp ^
|
||||
|
@ -87,6 +87,11 @@ void CHud::Think( void )
|
||||
// only let players adjust up in fov, and only if they are not overriden by something else
|
||||
m_iFOV = Q_max( default_fov->value, 90 );
|
||||
}
|
||||
|
||||
if( gEngfuncs.IsSpectateOnly() )
|
||||
{
|
||||
m_iFOV = gHUD.m_Spectator.GetFOV(); // default_fov->value;
|
||||
}
|
||||
}
|
||||
|
||||
// Redraw
|
||||
|
@ -37,8 +37,6 @@ extern "C" float vJumpAngles[3];
|
||||
extern void V_GetInEyePos( int entity, float * origin, float * angles );
|
||||
extern void V_ResetChaseCam();
|
||||
extern void V_GetChasePos( int target, float * cl_angles, float * origin, float * angles );
|
||||
extern void VectorAngles( const float *forward, float *angles );
|
||||
extern "C" void NormalizeAngles( float *angles );
|
||||
extern float * GetClientColor( int clientIndex );
|
||||
|
||||
extern vec3_t v_origin; // last view origin
|
||||
@ -46,6 +44,37 @@ extern vec3_t v_angles; // last view angle
|
||||
extern vec3_t v_cl_angles; // last client/mouse angle
|
||||
extern vec3_t v_sim_org; // last sim origin
|
||||
|
||||
#if 0
|
||||
const char *GetSpectatorLabel( int iMode )
|
||||
{
|
||||
switch( iMode )
|
||||
{
|
||||
case OBS_CHASE_LOCKED:
|
||||
return "#OBS_CHASE_LOCKED";
|
||||
|
||||
case OBS_CHASE_FREE:
|
||||
return "#OBS_CHASE_FREE";
|
||||
|
||||
case OBS_ROAMING:
|
||||
return "#OBS_ROAMING";
|
||||
|
||||
case OBS_IN_EYE:
|
||||
return "#OBS_IN_EYE";
|
||||
|
||||
case OBS_MAP_FREE:
|
||||
return "#OBS_MAP_FREE";
|
||||
|
||||
case OBS_MAP_CHASE:
|
||||
return "#OBS_MAP_CHASE";
|
||||
|
||||
case OBS_NONE:
|
||||
default:
|
||||
return "#OBS_NONE";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SpectatorMode( void )
|
||||
{
|
||||
if( gEngfuncs.Cmd_Argc() <= 1 )
|
||||
@ -152,6 +181,7 @@ int CHudSpectator::Init()
|
||||
m_flNextObserverInput = 0.0f;
|
||||
m_zoomDelta = 0.0f;
|
||||
m_moveDelta = 0.0f;
|
||||
m_FOV = 90.0f;
|
||||
m_chatEnabled = ( gHUD.m_SayText.m_HUD_saytext->value != 0 );
|
||||
iJumpSpectator = 0;
|
||||
|
||||
@ -363,6 +393,178 @@ void CHudSpectator::SetSpectatorStartPosition()
|
||||
iJumpSpectator = 1; // jump anyway
|
||||
}
|
||||
|
||||
void CHudSpectator::SetCameraView( vec3_t pos, vec3_t angle, float fov )
|
||||
{
|
||||
m_FOV = fov;
|
||||
VectorCopy( pos, vJumpOrigin );
|
||||
VectorCopy( angle, vJumpAngles );
|
||||
gEngfuncs.SetViewAngles( vJumpAngles );
|
||||
iJumpSpectator = 1; // jump anyway
|
||||
}
|
||||
|
||||
void CHudSpectator::AddWaypoint( float time, vec3_t pos, vec3_t angle, float fov, int flags )
|
||||
{
|
||||
if( flags == 0 && time == 0.0f )
|
||||
{
|
||||
// switch instantly to this camera view
|
||||
SetCameraView( pos, angle, fov );
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_NumWayPoints >= MAX_CAM_WAYPOINTS )
|
||||
{
|
||||
gEngfuncs.Con_Printf( "Too many camera waypoints!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy( angle, m_CamPath[m_NumWayPoints].angle );
|
||||
VectorCopy( pos, m_CamPath[m_NumWayPoints].position );
|
||||
m_CamPath[m_NumWayPoints].flags = flags;
|
||||
m_CamPath[m_NumWayPoints].fov = fov;
|
||||
m_CamPath[m_NumWayPoints].time = time;
|
||||
|
||||
gEngfuncs.Con_DPrintf( "Added waypoint %i\n", m_NumWayPoints );
|
||||
|
||||
m_NumWayPoints++;
|
||||
}
|
||||
|
||||
void CHudSpectator::SetWayInterpolation( cameraWayPoint_t *prev, cameraWayPoint_t *start, cameraWayPoint_t *end, cameraWayPoint_t *next )
|
||||
{
|
||||
m_WayInterpolation.SetViewAngles( start->angle, end->angle );
|
||||
|
||||
m_WayInterpolation.SetFOVs( start->fov, end->fov );
|
||||
|
||||
m_WayInterpolation.SetSmoothing( ( start->flags & DRC_FLAG_SLOWSTART ) != 0,
|
||||
( start->flags & DRC_FLAG_SLOWEND ) != 0 );
|
||||
|
||||
if( prev && next )
|
||||
{
|
||||
m_WayInterpolation.SetWaypoints( &prev->position, start->position, end->position, &next->position );
|
||||
}
|
||||
else if( prev )
|
||||
{
|
||||
m_WayInterpolation.SetWaypoints( &prev->position, start->position, end->position, NULL );
|
||||
}
|
||||
else if( next )
|
||||
{
|
||||
m_WayInterpolation.SetWaypoints( NULL, start->position, end->position, &next->position );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_WayInterpolation.SetWaypoints( NULL, start->position, end->position, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
bool CHudSpectator::GetDirectorCamera( vec3_t &position, vec3_t &angle )
|
||||
{
|
||||
float now = gHUD.m_flTime;
|
||||
float fov = 90.0f;
|
||||
|
||||
if( m_ChaseEntity )
|
||||
{
|
||||
cl_entity_t *ent = gEngfuncs.GetEntityByIndex( m_ChaseEntity );
|
||||
|
||||
if( ent )
|
||||
{
|
||||
vec3_t vt = ent->curstate.origin;
|
||||
|
||||
if( m_ChaseEntity <= gEngfuncs.GetMaxClients())
|
||||
{
|
||||
if( ent->curstate.solid == SOLID_NOT )
|
||||
{
|
||||
vt[2]+= -8 ; // PM_DEAD_VIEWHEIGHT
|
||||
}
|
||||
else if( ent->curstate.usehull == 1 )
|
||||
{
|
||||
vt[2]+= 12; // VEC_DUCK_VIEW;
|
||||
}
|
||||
else
|
||||
{
|
||||
vt[2]+= 28; // DEFAULT_VIEWHEIGHT
|
||||
}
|
||||
}
|
||||
|
||||
vt = vt - position;
|
||||
VectorAngles( vt, angle );
|
||||
angle[0] = -angle[0];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_IsInterpolating )
|
||||
return false;
|
||||
|
||||
if( m_WayPoint < 0 || m_WayPoint >= ( m_NumWayPoints - 1 ))
|
||||
return false;
|
||||
|
||||
cameraWayPoint_t *wp1 = &m_CamPath[m_WayPoint];
|
||||
cameraWayPoint_t *wp2 = &m_CamPath[m_WayPoint+1];
|
||||
|
||||
if( now < wp1->time )
|
||||
return false;
|
||||
|
||||
while( now > wp2->time )
|
||||
{
|
||||
// go to next waypoint, if possible
|
||||
m_WayPoint++;
|
||||
|
||||
if( m_WayPoint >= ( m_NumWayPoints - 1 ))
|
||||
{
|
||||
m_IsInterpolating = false;
|
||||
return false; // there is no following waypoint
|
||||
}
|
||||
|
||||
wp1 = wp2;
|
||||
wp2 = &m_CamPath[m_WayPoint + 1];
|
||||
|
||||
if( m_WayPoint > 0 )
|
||||
{
|
||||
// we have a predecessor
|
||||
|
||||
if( m_WayPoint < ( m_NumWayPoints - 1 ))
|
||||
{
|
||||
// we have also a successor
|
||||
SetWayInterpolation( &m_CamPath[m_WayPoint - 1], wp1, wp2, &m_CamPath[m_WayPoint + 2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWayInterpolation( &m_CamPath[m_WayPoint - 1], wp1, wp2, NULL );
|
||||
}
|
||||
}
|
||||
else if( m_WayPoint < ( m_NumWayPoints - 1 ))
|
||||
{
|
||||
// we only have a successor
|
||||
SetWayInterpolation( NULL, wp1, wp2, &m_CamPath[m_WayPoint + 2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have only two waypoints
|
||||
SetWayInterpolation( NULL, wp1, wp2, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
if( wp2->time <= wp1->time )
|
||||
return false;
|
||||
|
||||
float fraction = ( now - wp1->time ) / ( wp2->time - wp1->time );
|
||||
|
||||
if( fraction < 0.0f )
|
||||
fraction = 0.0f;
|
||||
else if( fraction > 1.0f )
|
||||
fraction = 1.0f;
|
||||
|
||||
m_WayInterpolation.Interpolate( fraction, position, angle, &fov );
|
||||
|
||||
// gEngfuncs.Con_Printf( "Interpolate time: %.2f, fraction %.2f, point : %.2f,%.2f,%.2f\n", now, fraction, position[0], position[1], position[2] );
|
||||
|
||||
SetCameraView( position, angle, fov );
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Loads new icons
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -377,9 +579,21 @@ int CHudSpectator::VidInit()
|
||||
m_hsprCamera = SPR_Load( "sprites/camera.spr" );
|
||||
m_hCrosshair = SPR_Load( "sprites/crosshairs.spr" );
|
||||
|
||||
m_lastPrimaryObject = m_lastSecondaryObject = 0;
|
||||
m_flNextObserverInput = 0.0f;
|
||||
m_lastHudMessage = 0;
|
||||
m_iSpectatorNumber = 0;
|
||||
iJumpSpectator = 0;
|
||||
g_iUser1 = g_iUser2 = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
float CHudSpectator::GetFOV( void )
|
||||
{
|
||||
return m_FOV;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flTime -
|
||||
@ -427,8 +641,11 @@ int CHudSpectator::Draw( float flTime )
|
||||
return 1;
|
||||
|
||||
// make sure we have player info
|
||||
#if USE_VGUI
|
||||
gViewPort->GetAllPlayersInfo();
|
||||
#else
|
||||
gHUD.GetAllPlayersInfo();
|
||||
|
||||
#endif
|
||||
// loop through all the players and draw additional infos to their sprites on the map
|
||||
for( int i = 0; i < MAX_PLAYERS; i++ )
|
||||
{
|
||||
@ -461,8 +678,10 @@ int CHudSpectator::Draw( float flTime )
|
||||
|
||||
void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
|
||||
{
|
||||
float value;
|
||||
float f1, f2;
|
||||
char *string;
|
||||
vec3_t v1, v2;
|
||||
int i1, i2, i3;
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
@ -479,7 +698,7 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
|
||||
gHUD.MsgFunc_InitHUD( NULL, 0, NULL );
|
||||
gHUD.MsgFunc_ResetHUD( NULL, 0, NULL );
|
||||
break;
|
||||
case DRC_CMD_EVENT:
|
||||
case DRC_CMD_EVENT: // old director style message
|
||||
m_lastPrimaryObject = READ_WORD();
|
||||
m_lastSecondaryObject = READ_WORD();
|
||||
m_iObserverFlags = READ_LONG();
|
||||
@ -502,19 +721,22 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
|
||||
}
|
||||
break;
|
||||
case DRC_CMD_CAMERA:
|
||||
v1[0] = READ_COORD(); // position
|
||||
v1[1] = READ_COORD();
|
||||
v1[2] = READ_COORD(); // vJumpOrigin
|
||||
|
||||
v1[0] = READ_COORD(); // view angle
|
||||
v1[1] = READ_COORD(); // vJumpAngles
|
||||
v1[2] = READ_COORD();
|
||||
|
||||
f1 = READ_BYTE(); // fov
|
||||
i1 = READ_WORD(); // target
|
||||
|
||||
if( m_autoDirector->value )
|
||||
{
|
||||
vJumpOrigin[0] = READ_COORD(); // position
|
||||
vJumpOrigin[1] = READ_COORD();
|
||||
vJumpOrigin[2] = READ_COORD();
|
||||
|
||||
vJumpAngles[0] = READ_COORD(); // view angle
|
||||
vJumpAngles[1] = READ_COORD();
|
||||
vJumpAngles[2] = READ_COORD();
|
||||
|
||||
gEngfuncs.SetViewAngles( vJumpAngles );
|
||||
|
||||
iJumpSpectator = 1;
|
||||
SetModes( OBS_ROAMING, -1 );
|
||||
SetCameraView( v1, v2, f1 );
|
||||
m_ChaseEntity = i1;
|
||||
}
|
||||
break;
|
||||
case DRC_CMD_MESSAGE:
|
||||
@ -551,13 +773,13 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
|
||||
break;
|
||||
case DRC_CMD_SOUND:
|
||||
string = READ_STRING();
|
||||
value = READ_FLOAT();
|
||||
f1 = READ_FLOAT();
|
||||
|
||||
// gEngfuncs.Con_Printf("DRC_CMD_FX_SOUND: %s %.2f\n", string, value );
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( 0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM );
|
||||
// gEngfuncs.Con_Printf("DRC_CMD_FX_SOUND: %s %.2f\n", string, f1 );
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( 0, v_origin, CHAN_BODY, string, f1, ATTN_NORM, 0, PITCH_NORM );
|
||||
break;
|
||||
case DRC_CMD_TIMESCALE:
|
||||
value = READ_FLOAT();
|
||||
f1 = READ_FLOAT();
|
||||
break;
|
||||
case DRC_CMD_STATUS:
|
||||
READ_LONG(); // total number of spectator slots
|
||||
@ -574,13 +796,71 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
|
||||
gViewPort->UpdateSpectatorPanel();
|
||||
#endif
|
||||
break;
|
||||
case DRC_CMD_FADE:
|
||||
break;
|
||||
case DRC_CMD_STUFFTEXT:
|
||||
gEngfuncs.pfnFilteredClientCmd( READ_STRING() );
|
||||
break;
|
||||
case DRC_CMD_CAMPATH:
|
||||
v1[0] = READ_COORD(); // position
|
||||
v1[1] = READ_COORD();
|
||||
v1[2] = READ_COORD(); // vJumpOrigin
|
||||
|
||||
v2[0] = READ_COORD(); // view angle
|
||||
v2[1] = READ_COORD(); // vJumpAngles
|
||||
v2[2] = READ_COORD();
|
||||
f1 = READ_BYTE(); // FOV
|
||||
i1 = READ_BYTE(); // flags
|
||||
|
||||
if( m_autoDirector->value )
|
||||
{
|
||||
SetModes( OBS_ROAMING, -1 );
|
||||
SetCameraView( v1, v2, f1 );
|
||||
}
|
||||
break;
|
||||
case DRC_CMD_WAYPOINTS:
|
||||
i1 = READ_BYTE();
|
||||
m_NumWayPoints = 0;
|
||||
m_WayPoint = 0;
|
||||
for( i2 = 0; i2 < i1; i2++ )
|
||||
{
|
||||
f1 = gHUD.m_flTime + (float)( READ_SHORT()) / 100.0f;
|
||||
|
||||
v1[0] = READ_COORD(); // position
|
||||
v1[1] = READ_COORD();
|
||||
v1[2] = READ_COORD(); // vJumpOrigin
|
||||
|
||||
v2[0] = READ_COORD(); // view angle
|
||||
v2[1] = READ_COORD(); // vJumpAngles
|
||||
v2[2] = READ_COORD();
|
||||
f2 = READ_BYTE(); // fov
|
||||
i3 = READ_BYTE(); // flags
|
||||
|
||||
AddWaypoint( f1, v1, v2, f2, i3 );
|
||||
}
|
||||
|
||||
// gEngfuncs.Con_Printf( "CHudSpectator::DirectorMessage: waypoints %i.\n", m_NumWayPoints );
|
||||
if( !m_autoDirector->value )
|
||||
{
|
||||
// ignore waypoints
|
||||
m_NumWayPoints = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
SetModes( OBS_ROAMING, -1 );
|
||||
|
||||
m_IsInterpolating = true;
|
||||
|
||||
if( m_NumWayPoints > 2 )
|
||||
{
|
||||
SetWayInterpolation( NULL, &m_CamPath[0], &m_CamPath[1], &m_CamPath[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWayInterpolation( NULL, &m_CamPath[0], &m_CamPath[1], NULL );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gEngfuncs.Con_DPrintf( "CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,9 +875,10 @@ void CHudSpectator::FindNextPlayer( bool bReverse )
|
||||
// if we are NOT in HLTV mode, spectator targets are set on server
|
||||
if( !gEngfuncs.IsSpectateOnly() )
|
||||
{
|
||||
char cmdstring[32];
|
||||
char cmdstring[256];
|
||||
// forward command to server
|
||||
sprintf( cmdstring, "follownext %i", bReverse ? 1 : 0 );
|
||||
_snprintf( cmdstring, sizeof( cmdstring ) - 1,"follownext %i", bReverse ? 1 : 0 );
|
||||
cmdstring[sizeof( cmdstring ) - 1] = '\0';
|
||||
gEngfuncs.pfnServerCmd( cmdstring );
|
||||
return;
|
||||
}
|
||||
@ -614,8 +895,11 @@ void CHudSpectator::FindNextPlayer( bool bReverse )
|
||||
int iDir = bReverse ? -1 : 1;
|
||||
|
||||
// make sure we have player info
|
||||
#if USE_VGUI
|
||||
gViewPort->GetAllPlayersInfo();
|
||||
#else
|
||||
gHUD.GetAllPlayersInfo();
|
||||
|
||||
#endif
|
||||
do
|
||||
{
|
||||
iCurrent += iDir;
|
||||
@ -664,9 +948,10 @@ void CHudSpectator::FindPlayer(const char *name)
|
||||
// if we are NOT in HLTV mode, spectator targets are set on server
|
||||
if ( !gEngfuncs.IsSpectateOnly() )
|
||||
{
|
||||
char cmdstring[32];
|
||||
char cmdstring[256];
|
||||
// forward command to server
|
||||
sprintf(cmdstring,"follow %s",name);
|
||||
_snprintf( cmdstring, sizeof( cmdstring ) - 1, "follow %s", name );
|
||||
cmdstring[sizeof( cmdstring ) - 1] = '\0';
|
||||
gEngfuncs.pfnServerCmd( cmdstring );
|
||||
return;
|
||||
}
|
||||
@ -674,8 +959,11 @@ void CHudSpectator::FindPlayer(const char *name)
|
||||
g_iUser2 = 0;
|
||||
|
||||
// make sure we have player info
|
||||
#if USE_VGUI
|
||||
gViewPort->GetAllPlayersInfo();
|
||||
#else
|
||||
gHUD.GetAllPlayersInfo();
|
||||
|
||||
#endif
|
||||
cl_entity_t * pEnt = NULL;
|
||||
|
||||
for (int i = 1; i < MAX_PLAYERS; i++ )
|
||||
@ -847,12 +1135,20 @@ void CHudSpectator::SetModes( int iNewMainMode, int iNewInsetMode )
|
||||
return;
|
||||
}
|
||||
|
||||
// main modes ettings will override inset window settings
|
||||
m_IsInterpolating = false;
|
||||
m_ChaseEntity = 0;
|
||||
|
||||
// main modes settings will override inset window settings
|
||||
if( iNewMainMode != g_iUser1 )
|
||||
{
|
||||
// if we are NOT in HLTV mode, main spectator mode is set on server
|
||||
if( !gEngfuncs.IsSpectateOnly() )
|
||||
{
|
||||
char cmdstring[256];
|
||||
// forward command to server
|
||||
_snprintf( cmdstring, sizeof( cmdstring ) - 1,"specmode %i", iNewMainMode );
|
||||
cmdstring[sizeof( cmdstring ) - 1] = '\0';
|
||||
gEngfuncs.pfnServerCmd( cmdstring );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1548,8 +1844,9 @@ void CHudSpectator::CheckSettings()
|
||||
if( gEngfuncs.IsSpectateOnly() )
|
||||
{
|
||||
// tell proxy our new chat mode
|
||||
char chatcmd[32];
|
||||
sprintf( chatcmd, "ignoremsg %i", m_chatEnabled ? 0 : 1 );
|
||||
char chatcmd[256];
|
||||
_snprintf( chatcmd, sizeof( chatcmd ) - 1, "ignoremsg %i", m_chatEnabled ? 0 : 1 );
|
||||
chatcmd[sizeof( chatcmd ) - 1] = '\0';
|
||||
gEngfuncs.pfnServerCmd( chatcmd );
|
||||
}
|
||||
}
|
||||
@ -1626,6 +1923,12 @@ void CHudSpectator::Reset()
|
||||
|
||||
memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities) );
|
||||
|
||||
m_FOV = 90.0f;
|
||||
|
||||
m_IsInterpolating = false;
|
||||
|
||||
m_ChaseEntity = 0;
|
||||
|
||||
SetSpectatorStartPosition();
|
||||
}
|
||||
|
||||
@ -1648,7 +1951,7 @@ void CHudSpectator::InitHUDData()
|
||||
|
||||
Reset();
|
||||
|
||||
SetModes( OBS_CHASE_FREE, INSET_OFF );
|
||||
SetModes( OBS_CHASE_LOCKED, INSET_OFF );
|
||||
|
||||
g_iUser2 = 0; // fake not target until first camera command
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define HUD_SPECTATOR_H
|
||||
|
||||
#include "cl_entity.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
#define INSET_OFF 0
|
||||
#define INSET_CHASE_FREE 1
|
||||
@ -22,6 +23,9 @@
|
||||
#define OVERVIEW_TILE_SIZE 128 // don't change this
|
||||
#define OVERVIEW_MAX_LAYERS 1
|
||||
|
||||
extern void VectorAngles( const float *forward, float *angles );
|
||||
extern "C" void NormalizeAngles( float *angles );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it )
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -49,7 +53,17 @@ typedef struct overviewEntity_s
|
||||
double killTime;
|
||||
} overviewEntity_t;
|
||||
|
||||
typedef struct cameraWayPoint_s
|
||||
{
|
||||
float time;
|
||||
vec3_t position;
|
||||
vec3_t angle;
|
||||
float fov;
|
||||
int flags;
|
||||
} cameraWayPoint_t;
|
||||
|
||||
#define MAX_OVERVIEW_ENTITIES 128
|
||||
#define MAX_CAM_WAYPOINTS 32
|
||||
|
||||
class CHudSpectator : public CHudBase
|
||||
{
|
||||
@ -81,6 +95,13 @@ public:
|
||||
|
||||
int Draw( float flTime );
|
||||
|
||||
void AddWaypoint( float time, vec3_t pos, vec3_t angle, float fov, int flags );
|
||||
void SetCameraView( vec3_t pos, vec3_t angle, float fov );
|
||||
float GetFOV();
|
||||
bool GetDirectorCamera( vec3_t &position, vec3_t &angle );
|
||||
void SetWayInterpolation( cameraWayPoint_t *prev, cameraWayPoint_t *start, cameraWayPoint_t *end, cameraWayPoint_t *next );
|
||||
|
||||
|
||||
int m_iDrawCycle;
|
||||
client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES];
|
||||
char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128];
|
||||
@ -100,8 +121,13 @@ public:
|
||||
|
||||
qboolean m_chatEnabled;
|
||||
|
||||
qboolean m_IsInterpolating;
|
||||
int m_ChaseEntity; // if != 0, follow this entity with viewangles
|
||||
int m_WayPoint; // current waypoint 1
|
||||
int m_NumWayPoints; // current number of waypoints
|
||||
vec3_t m_cameraOrigin; // a help camera
|
||||
vec3_t m_cameraAngles; // and it's angles
|
||||
CInterpolation m_WayInterpolation;
|
||||
|
||||
private:
|
||||
vec3_t m_vPlayerPos[MAX_PLAYERS];
|
||||
@ -119,9 +145,11 @@ private:
|
||||
|
||||
struct model_s *m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame
|
||||
float m_flNextObserverInput;
|
||||
float m_FOV;
|
||||
float m_zoomDelta;
|
||||
float m_moveDelta;
|
||||
int m_lastPrimaryObject;
|
||||
int m_lastSecondaryObject;
|
||||
cameraWayPoint_t m_CamPath[MAX_CAM_WAYPOINTS];
|
||||
};
|
||||
#endif // SPECTATOR_H
|
||||
|
217
cl_dll/interpolation.cpp
Normal file
217
cl_dll/interpolation.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/************ (C) Copyright 2003 Valve, L.L.C. All rights reserved. ***********
|
||||
**
|
||||
** The copyright to the contents herein is the property of Valve, L.L.C.
|
||||
** The contents may be used and/or copied only with the written permission of
|
||||
** Valve, L.L.C., or in accordance with the terms and conditions stipulated in
|
||||
** the agreement/contract under which the contents have been supplied.
|
||||
**
|
||||
*******************************************************************************
|
||||
**
|
||||
** Contents:
|
||||
**
|
||||
** interpolation.cpp: implementation of the interpolation class
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
// = determinant of matrix a,b,c
|
||||
#define Determinant( a, b, c ) ( (a)[2] * ( (b)[0]*(c)[1] - (b)[1]*(c)[0] ) + \
|
||||
(a)[1] * ( (b)[2]*(c)[0] - (b)[0]*(c)[2] ) + \
|
||||
(a)[0] * ( (b)[1]*(c)[2] - (b)[2]*(c)[1] ) )
|
||||
|
||||
// solve 3 vector linear system of equations v0 = x*v1 + y*v2 + z*v3 (if possible)
|
||||
bool SolveLSE( vec3_t v0, vec3_t v1, vec3_t v2, vec3_t v3, float * x, float * y, float * z )
|
||||
{
|
||||
float d = Determinant( v1, v2, v3 );
|
||||
|
||||
if( d == 0.0f )
|
||||
return false;
|
||||
|
||||
if( x )
|
||||
*x = Determinant( v0, v2, v3 ) / d;
|
||||
|
||||
if( y )
|
||||
*y= Determinant( v1, v0, v3 ) / d;
|
||||
|
||||
if( z )
|
||||
*z= Determinant( v1, v2, v0 ) / d;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// p = closest point between vector lines a1+x*m1 and a2+x*m2
|
||||
bool GetPointBetweenLines( vec3_t &p, vec3_t a1, vec3_t m1, vec3_t a2, vec3_t m2 )
|
||||
{
|
||||
float x, z;
|
||||
|
||||
vec3_t t1 = CrossProduct( m1, m2 );
|
||||
vec3_t t2 = a2 - a1;
|
||||
|
||||
if( !SolveLSE( t2, m1, t1, m2, &x , NULL, &z ) )
|
||||
return false;
|
||||
|
||||
t1 = a1 + x * m1;
|
||||
t2 = a2 + ( -z ) * m2;
|
||||
|
||||
p = ( t1 + t2 ) / 2.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bernstein Poynom B(u) with n = 2, i = 0
|
||||
#define BernsteinPolynom20(u) ( ( 1.0f - u ) * ( 1.0f - u ))
|
||||
#define BernsteinPolynom21(u) ( 2.0f * u * ( 1.0f - u ) )
|
||||
#define BernsteinPolynom22(u) ( u * u )
|
||||
|
||||
CInterpolation::CInterpolation()
|
||||
{
|
||||
}
|
||||
|
||||
CInterpolation::~CInterpolation()
|
||||
{
|
||||
m_SmoothStart = m_SmoothEnd = false;
|
||||
}
|
||||
|
||||
void CInterpolation::SetViewAngles( vec3_t start, vec3_t end )
|
||||
{
|
||||
m_StartAngle = start;
|
||||
m_EndAngle = end;
|
||||
NormalizeAngles( m_StartAngle );
|
||||
NormalizeAngles( m_EndAngle );
|
||||
}
|
||||
|
||||
void CInterpolation::SetFOVs( float start, float end )
|
||||
{
|
||||
m_StartFov = start;
|
||||
m_EndFov = end;
|
||||
}
|
||||
|
||||
void CInterpolation::SetWaypoints( vec3_t *prev, vec3_t start, vec3_t end, vec3_t *next )
|
||||
{
|
||||
m_StartPoint = start;
|
||||
m_EndPoint = end;
|
||||
|
||||
|
||||
vec3_t a, b, c, d;
|
||||
|
||||
if( !prev && !next )
|
||||
{
|
||||
// no direction given, straight linear interpolation
|
||||
m_Center = ( m_StartPoint + m_EndPoint ) / 2.0f;
|
||||
}
|
||||
else if( !prev )
|
||||
{
|
||||
a = start - end;
|
||||
float dist = a.Length() / 2.0f;
|
||||
a = a.Normalize();
|
||||
b = *next - end;
|
||||
b = b.Normalize();
|
||||
c = a - b;
|
||||
c = c.Normalize();
|
||||
m_Center = end + c * dist;
|
||||
}
|
||||
else if( !next )
|
||||
{
|
||||
a = *prev - start;
|
||||
a = a.Normalize();
|
||||
b = end - start;
|
||||
float dist = b.Length() / 2.0f;
|
||||
b = b.Normalize();
|
||||
c = b - a;
|
||||
c = c.Normalize();
|
||||
m_Center = start + c * dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have a previous and a next point, great!
|
||||
a = *prev - start;
|
||||
a = a.Normalize();
|
||||
b = end - start;
|
||||
b = b.Normalize();
|
||||
c = b - a;
|
||||
|
||||
a = start - end;
|
||||
a = a.Normalize();
|
||||
b = *next - end;
|
||||
b = b.Normalize();
|
||||
d = a - b;
|
||||
|
||||
GetPointBetweenLines( m_Center, start, c, end, d );
|
||||
}
|
||||
}
|
||||
|
||||
void CInterpolation::Interpolate( float t, vec3_t &point, vec3_t &angle, float *fov )
|
||||
{
|
||||
if( m_SmoothStart && m_SmoothEnd )
|
||||
{
|
||||
t = ( 1.0f - t ) * ( t * t ) + t * ( 1.0f - ( ( t - 1.0f ) * ( t - 1.0f )));
|
||||
}
|
||||
else if( m_SmoothStart )
|
||||
{
|
||||
t = t * t;
|
||||
}
|
||||
else if( m_SmoothEnd )
|
||||
{
|
||||
t = t - 1.0f;
|
||||
t = -( t * t ) + 1;
|
||||
}
|
||||
|
||||
if( point )
|
||||
{
|
||||
BezierInterpolatePoint( t, point );
|
||||
}
|
||||
|
||||
if( angle )
|
||||
{
|
||||
InterpolateAngle( t, angle );
|
||||
}
|
||||
|
||||
if( fov )
|
||||
{
|
||||
*fov = m_StartFov + ( t * ( m_EndFov - m_StartFov ));
|
||||
}
|
||||
}
|
||||
|
||||
void CInterpolation::BezierInterpolatePoint( float t, vec3_t &point )
|
||||
{
|
||||
point = m_StartPoint * BernsteinPolynom20( t );
|
||||
point = point + m_Center * BernsteinPolynom21( t );
|
||||
point = point + m_EndPoint * BernsteinPolynom22( t );
|
||||
}
|
||||
|
||||
void CInterpolation::SetSmoothing( bool start, bool end )
|
||||
{
|
||||
m_SmoothStart = start;
|
||||
m_SmoothEnd = end;
|
||||
}
|
||||
|
||||
void CInterpolation::InterpolateAngle( float t, vec3_t &angle )
|
||||
{
|
||||
int i;
|
||||
float ang1, ang2;
|
||||
float d;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
ang1 = m_StartAngle[i];
|
||||
ang2 = m_EndAngle[i];
|
||||
|
||||
d = ang2 - ang1;
|
||||
if ( d > 180 )
|
||||
{
|
||||
d -= 360;
|
||||
}
|
||||
else if ( d < -180 )
|
||||
{
|
||||
d += 360;
|
||||
}
|
||||
|
||||
angle[i] = ang1 + d * t;
|
||||
}
|
||||
|
||||
NormalizeAngles( angle );
|
||||
}
|
||||
|
52
cl_dll/interpolation.h
Normal file
52
cl_dll/interpolation.h
Normal file
@ -0,0 +1,52 @@
|
||||
/************ (C) Copyright 2003 Valve, L.L.C. All rights reserved. ***********
|
||||
**
|
||||
** The copyright to the contents herein is the property of Valve, L.L.C.
|
||||
** The contents may be used and/or copied only with the written permission of
|
||||
** Valve, L.L.C., or in accordance with the terms and conditions stipulated in
|
||||
** the agreement/contract under which the contents have been supplied.
|
||||
**
|
||||
*******************************************************************************
|
||||
**
|
||||
** Contents:
|
||||
**
|
||||
** interpolation.h: Bezier inpolation classes
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#if !defined(INTERPOLATION_H)
|
||||
#define INTERPOLATION_H
|
||||
|
||||
|
||||
// interpolation class
|
||||
class CInterpolation
|
||||
{
|
||||
public:
|
||||
CInterpolation();
|
||||
virtual ~CInterpolation();
|
||||
|
||||
void SetWaypoints( vec3_t *prev, vec3_t start, vec3_t end, vec3_t *next );
|
||||
void SetViewAngles( vec3_t start, vec3_t end );
|
||||
void SetFOVs( float start, float end );
|
||||
void SetSmoothing( bool start, bool end );
|
||||
|
||||
// get interpolated point 0 =< t =< 1, 0 = start, 1 = end
|
||||
void Interpolate( float t, vec3_t &point, vec3_t &angle, float * fov );
|
||||
|
||||
protected:
|
||||
void BezierInterpolatePoint( float t, vec3_t &point );
|
||||
void InterpolateAngle( float t, vec3_t &angle );
|
||||
|
||||
vec3_t m_StartPoint;
|
||||
vec3_t m_EndPoint;
|
||||
vec3_t m_StartAngle;
|
||||
vec3_t m_EndAngle;
|
||||
vec3_t m_Center;
|
||||
float m_StartFov;
|
||||
float m_EndFov;
|
||||
|
||||
bool m_SmoothStart;
|
||||
bool m_SmoothEnd;
|
||||
};
|
||||
|
||||
#endif // INTERPOLATION_H
|
@ -1462,6 +1462,8 @@ void V_CalcSpectatorRefdef( struct ref_params_s * pparams )
|
||||
case OBS_ROAMING:
|
||||
VectorCopy( v_cl_angles, v_angles );
|
||||
VectorCopy( v_sim_org, v_origin );
|
||||
// override values if director is active
|
||||
gHUD.m_Spectator.GetDirectorCamera(v_origin, v_angles);
|
||||
break;
|
||||
case OBS_IN_EYE:
|
||||
V_CalcNormalRefdef( pparams );
|
||||
|
@ -37,11 +37,14 @@
|
||||
#define DRC_CMD_SOUND 7 // plays a particular sound
|
||||
#define DRC_CMD_STATUS 8 // status info about broadcast
|
||||
#define DRC_CMD_BANNER 9 // banner file name for HLTV gui
|
||||
#define DRC_CMD_FADE 10 // send screen fade command
|
||||
#define DRC_CMD_SHAKE 11 // send screen shake command
|
||||
#define DRC_CMD_STUFFTEXT 12 // like the normal svc_stufftext but as director command
|
||||
#define DRC_CMD_STUFFTEXT 10 // like the normal svc_stufftext but as director command
|
||||
#define DRC_CMD_CHASE 11 // chase a certain player
|
||||
#define DRC_CMD_INEYE 12 // view player through own eyes
|
||||
#define DRC_CMD_MAP 13 // show overview map
|
||||
#define DRC_CMD_CAMPATH 14 // define camera waypoint
|
||||
#define DRC_CMD_WAYPOINTS 15 // start moving camera, inetranl message
|
||||
|
||||
#define DRC_CMD_LAST 12
|
||||
#define DRC_CMD_LAST 15
|
||||
|
||||
// HLTV_EVENT event flags
|
||||
#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important)
|
||||
@ -53,7 +56,9 @@
|
||||
#define DRC_FLAG_FINAL (1<<9) // is a final scene
|
||||
#define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data
|
||||
|
||||
#define MAX_DIRECTOR_CMD_PARAMETERS 4
|
||||
#define MAX_DIRECTOR_CMD_STRING 128
|
||||
// DRC_CMD_WAYPOINT flags
|
||||
#define DRC_FLAG_STARTPATH 1 // end with speed 0.0
|
||||
#define DRC_FLAG_SLOWSTART 2 // start with speed 0.0
|
||||
#define DRC_FLAG_SLOWEND 4 // end with speed 0.0
|
||||
|
||||
#endif//HLTV_H
|
||||
|
@ -270,6 +270,7 @@ files{"cl_dll/hl/hl_baseentity.cpp",
|
||||
"cl_dll/input_goldsource.cpp",
|
||||
"cl_dll/input_mouse.cpp",
|
||||
"cl_dll/input_xash3d.cpp",
|
||||
"cl_dll/interpolation.cpp",
|
||||
"cl_dll/menu.cpp",
|
||||
"cl_dll/message.cpp",
|
||||
"cl_dll/overview.cpp",
|
||||
|
Loading…
Reference in New Issue
Block a user