mirror of
https://github.com/ENSL/NS.git
synced 2024-11-22 12:41:33 +00:00
b5177e8e47
- fixed issues with piemenu cursor code being enabled when spectating - the cursor is now enabled when in an observer mode that locks the view. - fixed bugs/exploits where dead players could first person spectate the enemy team or travel around in freelook if all spectatable players on the team are dead.
1965 lines
51 KiB
C++
1965 lines
51 KiB
C++
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
|
||
//
|
||
// Purpose:
|
||
//
|
||
// $NoKeywords: $
|
||
//=============================================================================
|
||
|
||
#include "hud.h"
|
||
#include "cl_util.h"
|
||
#include "common/cl_entity.h"
|
||
#include "common/triangleapi.h"
|
||
#include "vgui_TeamFortressViewport.h"
|
||
#include "vgui_SpectatorPanel.h"
|
||
#include "common/hltv.h"
|
||
#include "AvHServerVariables.h"
|
||
#include "ammohistory.h"
|
||
|
||
#include "pm_shared/pm_shared.h"
|
||
#include "pm_shared/pm_defs.h"
|
||
#include "common/pmtrace.h"
|
||
#include "common/entity_types.h"
|
||
|
||
// these are included for the math functions
|
||
#include "common/com_model.h"
|
||
#include "common/demo_api.h"
|
||
#include "common/event_api.h"
|
||
#include "studio_util.h"
|
||
#include "common/screenfade.h"
|
||
#include "util/STLUtil.h"
|
||
#include "mod/AvHTitles.h"
|
||
#include "mod/AvHSprites.h"
|
||
|
||
#pragma warning(disable: 4244)
|
||
|
||
extern int iJumpSpectator;
|
||
extern float vJumpOrigin[3];
|
||
extern 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
|
||
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
|
||
|
||
void SpectatorMode(void)
|
||
{
|
||
|
||
if ( gEngfuncs.Cmd_Argc() <= 1 )
|
||
{
|
||
gEngfuncs.Con_Printf( "usage: spec_mode <Mode>\n" );
|
||
return;
|
||
}
|
||
|
||
// SetModes() will decide if command is executed on server or local
|
||
if ( gEngfuncs.Cmd_Argc() == 2 )
|
||
gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ));
|
||
|
||
//else if ( gEngfuncs.Cmd_Argc() == 3 )
|
||
// gHUD.m_Spectator.SetMode( atoi( gEngfuncs.Cmd_Argv(1) ), atoi( gEngfuncs.Cmd_Argv(2) ) );
|
||
}
|
||
|
||
void SpectatorSpray(void)
|
||
{
|
||
vec3_t forward;
|
||
char string[128];
|
||
|
||
if ( !gEngfuncs.IsSpectateOnly() )
|
||
return;
|
||
|
||
AngleVectors(v_angles,forward,NULL,NULL);
|
||
VectorScale(forward, 128, forward);
|
||
VectorAdd(forward, v_origin, forward);
|
||
pmtrace_t * trace = gEngfuncs.PM_TraceLine( v_origin, forward, PM_TRACELINE_PHYSENTSONLY, 2, -1 );
|
||
if ( trace->fraction != 1.0 )
|
||
{
|
||
sprintf(string, "drc_spray %.2f %.2f %.2f %i",
|
||
trace->endpos[0], trace->endpos[1], trace->endpos[2], trace->ent );
|
||
gEngfuncs.pfnServerCmd(string);
|
||
}
|
||
|
||
}
|
||
void SpectatorHelp(void)
|
||
{
|
||
if ( gViewPort )
|
||
{
|
||
gViewPort->ShowVGUIMenu( MENU_SPECHELP );
|
||
}
|
||
else
|
||
{
|
||
char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" );
|
||
|
||
if ( text )
|
||
{
|
||
while ( *text )
|
||
{
|
||
if ( *text != 13 )
|
||
gEngfuncs.Con_Printf( "%c", *text );
|
||
text++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void SpectatorMenu( void )
|
||
{
|
||
if ( gEngfuncs.Cmd_Argc() <= 1 )
|
||
{
|
||
gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" );
|
||
return;
|
||
}
|
||
|
||
gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv(1))!=0 );
|
||
}
|
||
|
||
void ToggleScores( void )
|
||
{
|
||
if ( gViewPort )
|
||
{
|
||
if (gViewPort->IsScoreBoardVisible() )
|
||
{
|
||
gViewPort->HideScoreBoard();
|
||
}
|
||
else
|
||
{
|
||
gViewPort->ShowScoreBoard();
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
//-----------------------------------------------------------------------------
|
||
int CHudSpectator::Init()
|
||
{
|
||
gHUD.AddHudElem(this);
|
||
|
||
m_iFlags |= HUD_ACTIVE;
|
||
m_flNextObserverInput = 0.0f;
|
||
m_zoomDelta = 0.0f;
|
||
m_moveDelta = 0.0f;
|
||
iJumpSpectator = 0;
|
||
|
||
memset( &m_OverviewData, 0, sizeof(m_OverviewData));
|
||
memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
|
||
m_lastPrimaryObject = m_lastSecondaryObject = 0;
|
||
|
||
gEngfuncs.pfnAddCommand ("spec_mode", SpectatorMode );
|
||
gEngfuncs.pfnAddCommand ("spec_decal", SpectatorSpray );
|
||
gEngfuncs.pfnAddCommand ("spec_help", SpectatorHelp );
|
||
gEngfuncs.pfnAddCommand ("spec_menu", SpectatorMenu );
|
||
gEngfuncs.pfnAddCommand ("togglescores", ToggleScores );
|
||
|
||
m_drawnames = gEngfuncs.pfnRegisterVariable("spec_drawnames","1",0);
|
||
m_drawcone = gEngfuncs.pfnRegisterVariable("spec_drawcone","1",0);
|
||
m_drawstatus = gEngfuncs.pfnRegisterVariable("spec_drawstatus","1",0);
|
||
m_autoDirector = gEngfuncs.pfnRegisterVariable("spec_autodirector","1",0);
|
||
|
||
// Removed by mmcguire.
|
||
m_overviewMode = false;
|
||
//m_overview = gEngfuncs.pfnRegisterVariable("spec_overview","1",0);
|
||
//m_pip = gEngfuncs.pfnRegisterVariable("spec_pip","1",0);
|
||
|
||
if ( !m_drawnames || !m_drawcone || !m_drawstatus || !m_autoDirector /*|| !m_pip*/)
|
||
{
|
||
gEngfuncs.Con_Printf("ERROR! Couldn't register all spectator variables.\n");
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// UTIL_StringToVector originally from ..\dlls\util.cpp, slightly changed
|
||
//-----------------------------------------------------------------------------
|
||
|
||
void UTIL_StringToVector( float * pVector, const char *pString )
|
||
{
|
||
char *pstr, *pfront, tempString[128];
|
||
int j;
|
||
|
||
strcpy( tempString, pString );
|
||
pstr = pfront = tempString;
|
||
|
||
for ( j = 0; j < 3; j++ )
|
||
{
|
||
pVector[j] = atof( pfront );
|
||
|
||
while ( *pstr && *pstr != ' ' )
|
||
pstr++;
|
||
if (!*pstr)
|
||
break;
|
||
pstr++;
|
||
pfront = pstr;
|
||
}
|
||
|
||
if (j < 2)
|
||
{
|
||
for (j = j+1;j < 3; j++)
|
||
pVector[j] = 0;
|
||
}
|
||
}
|
||
|
||
int UTIL_FindEntityInMap(char * name, float * origin, float * angle)
|
||
{
|
||
int n,found = 0;
|
||
char keyname[256];
|
||
char token[1024];
|
||
|
||
cl_entity_t * pEnt = gEngfuncs.GetEntityByIndex( 0 ); // get world model
|
||
|
||
if ( !pEnt ) return 0;
|
||
|
||
if ( !pEnt->model ) return 0;
|
||
|
||
char * data = pEnt->model->entities;
|
||
|
||
while (data)
|
||
{
|
||
data = gEngfuncs.COM_ParseFile(data, token);
|
||
|
||
if ( (token[0] == '}') || (token[0]==0) )
|
||
break;
|
||
|
||
if (!data)
|
||
{
|
||
gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
|
||
return 0;
|
||
}
|
||
|
||
if (token[0] != '{')
|
||
{
|
||
gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: expected {\n");
|
||
return 0;
|
||
}
|
||
|
||
// we parse the first { now parse entities properties
|
||
|
||
while ( 1 )
|
||
{
|
||
// parse key
|
||
data = gEngfuncs.COM_ParseFile(data, token);
|
||
if (token[0] == '}')
|
||
break; // finish parsing this entity
|
||
|
||
if (!data)
|
||
{
|
||
gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
|
||
return 0;
|
||
};
|
||
|
||
strcpy (keyname, token);
|
||
|
||
// another hack to fix keynames with trailing spaces
|
||
n = (int)strlen(keyname);
|
||
while (n && keyname[n-1] == ' ')
|
||
{
|
||
keyname[n-1] = 0;
|
||
n--;
|
||
}
|
||
|
||
// parse value
|
||
data = gEngfuncs.COM_ParseFile(data, token);
|
||
if (!data)
|
||
{
|
||
gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n");
|
||
return 0;
|
||
};
|
||
|
||
if (token[0] == '}')
|
||
{
|
||
gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: closing brace without data");
|
||
return 0;
|
||
}
|
||
|
||
if (!strcmp(keyname,"classname"))
|
||
{
|
||
if (!strcmp(token, name ))
|
||
{
|
||
found = 1; // thats our entity
|
||
}
|
||
};
|
||
|
||
if( !strcmp( keyname, "angle" ) )
|
||
{
|
||
float y = atof( token );
|
||
|
||
if (y >= 0)
|
||
{
|
||
angle[0] = 0.0f;
|
||
angle[1] = y;
|
||
}
|
||
else if ((int)y == -1)
|
||
{
|
||
angle[0] = -90.0f;
|
||
angle[1] = 0.0f;;
|
||
}
|
||
else
|
||
{
|
||
angle[0] = 90.0f;
|
||
angle[1] = 0.0f;
|
||
}
|
||
|
||
angle[2] = 0.0f;
|
||
}
|
||
|
||
if( !strcmp( keyname, "angles" ) )
|
||
{
|
||
UTIL_StringToVector(angle, token);
|
||
}
|
||
|
||
if (!strcmp(keyname,"origin"))
|
||
{
|
||
UTIL_StringToVector(origin, token);
|
||
|
||
};
|
||
|
||
} // while (1)
|
||
|
||
if (found)
|
||
return 1;
|
||
|
||
}
|
||
|
||
return 0; // we search all entities, but didn't found the correct
|
||
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// SetSpectatorStartPosition():
|
||
// Get valid map position and 'beam' spectator to this position
|
||
//-----------------------------------------------------------------------------
|
||
|
||
void CHudSpectator::SetSpectatorStartPosition()
|
||
{
|
||
// search for info_player start
|
||
if ( UTIL_FindEntityInMap( "trigger_camera", m_cameraOrigin, m_cameraAngles ) )
|
||
iJumpSpectator = 1;
|
||
|
||
else if ( UTIL_FindEntityInMap( "info_player_start", m_cameraOrigin, m_cameraAngles ) )
|
||
iJumpSpectator = 1;
|
||
|
||
else if ( UTIL_FindEntityInMap( "info_player_deathmatch", m_cameraOrigin, m_cameraAngles ) )
|
||
iJumpSpectator = 1;
|
||
|
||
else if ( UTIL_FindEntityInMap( "info_player_coop", m_cameraOrigin, m_cameraAngles ) )
|
||
iJumpSpectator = 1;
|
||
else
|
||
{
|
||
// jump to 0,0,0 if no better position was found
|
||
VectorCopy(vec3_origin, m_cameraOrigin);
|
||
VectorCopy(vec3_origin, m_cameraAngles);
|
||
}
|
||
|
||
VectorCopy(m_cameraOrigin, vJumpOrigin);
|
||
VectorCopy(m_cameraAngles, vJumpAngles);
|
||
|
||
iJumpSpectator = 1; // jump anyway
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Loads new icons
|
||
//-----------------------------------------------------------------------------
|
||
int CHudSpectator::VidInit()
|
||
{
|
||
m_hsprPlayerMarine = SPR_Load("sprites/iplayerm.spr");
|
||
m_hsprPlayerAlien = SPR_Load("sprites/iplayera.spr");
|
||
m_hsprPlayerDead = SPR_Load("sprites/iplayerdead.spr");
|
||
m_hsprUnkownMap = SPR_Load("sprites/tile.spr");
|
||
//m_hsprBeam = SPR_Load("sprites/laserbeam.spr");
|
||
//m_hsprCamera = SPR_Load("sprites/camera.spr");
|
||
m_hCrosshair = SPR_Load("sprites/crosshairs.spr");
|
||
m_hsprWhite = SPR_Load(kWhiteSprite);
|
||
|
||
return 1;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose:
|
||
// Input : flTime -
|
||
// intermission -
|
||
//-----------------------------------------------------------------------------
|
||
int CHudSpectator::Draw(float flTime)
|
||
{
|
||
|
||
// draw only in spectator mode
|
||
if ( !g_iUser1 )
|
||
return 0;
|
||
// string error;
|
||
// gHUD.Update( flTime, error);
|
||
|
||
// Removed by mmcguire.
|
||
/*
|
||
// if user pressed zoom, aplly changes
|
||
if ( (m_zoomDelta != 0.0f) && ( g_iUser1 == OBS_MAP_FREE ) )
|
||
{
|
||
m_mapZoom += m_zoomDelta;
|
||
|
||
if ( m_mapZoom > 3.0f )
|
||
m_mapZoom = 3.0f;
|
||
|
||
if ( m_mapZoom < 0.5f )
|
||
m_mapZoom = 0.5f;
|
||
}
|
||
|
||
// if user moves in map mode, change map origin
|
||
if ( (m_moveDelta != 0.0f) && (g_iUser1 != OBS_ROAMING) )
|
||
{
|
||
vec3_t right;
|
||
AngleVectors(v_angles, NULL, right, NULL);
|
||
VectorNormalize(right);
|
||
VectorScale(right, m_moveDelta, right );
|
||
|
||
VectorAdd( m_mapOrigin, right, m_mapOrigin )
|
||
|
||
}
|
||
*/
|
||
|
||
//DrawOverviewMap();
|
||
|
||
/*
|
||
if (!IsInOverviewMode())
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
if (m_hsprWhite != NULL)
|
||
{
|
||
|
||
float bgColor[] = { 0.1, 0.1, 0.1, 1 };
|
||
float borderColor[] = { 1, 1, 1, 1 };
|
||
|
||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||
gEngfuncs.pTriAPI->CullFace(TRI_NONE);
|
||
|
||
gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
|
||
|
||
float gammaScale = 1.0f / gHUD.GetGammaSlope();
|
||
|
||
// Draw the border on the overview map and the inset view.
|
||
|
||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||
gEngfuncs.pTriAPI->CullFace(TRI_NONE);
|
||
|
||
gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
|
||
gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
|
||
|
||
gEngfuncs.pTriAPI->Begin(TRI_LINES);
|
||
|
||
int insetX1 = XRES(m_OverviewData.insetWindowX);
|
||
int insetY1 = YRES(m_OverviewData.insetWindowY);
|
||
int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
|
||
int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
|
||
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
}*/
|
||
|
||
|
||
|
||
/*
|
||
// Only draw the icon names only if map mode is in Main Mode
|
||
if ( g_iUser1 < OBS_MAP_FREE )
|
||
return 1;
|
||
|
||
if ( !m_drawnames->value )
|
||
return 1;
|
||
|
||
// make sure we have player info
|
||
gViewPort->GetAllPlayersInfo();
|
||
*/
|
||
|
||
return 1;
|
||
|
||
}
|
||
|
||
bool CHudSpectator::IsInOverviewMode() const
|
||
{
|
||
return g_iUser1 && m_overviewMode && gHUD.GetIsNSMode() /*&& g_iUser1 != OBS_ROAMING*/;
|
||
}
|
||
|
||
void CHudSpectator::SetOverviewMode(bool overviewMode)
|
||
{
|
||
m_overviewMode = overviewMode;
|
||
}
|
||
|
||
void CHudSpectator::DrawOverviewMap()
|
||
{
|
||
|
||
// draw only in spectator mode
|
||
if (!IsInOverviewMode())
|
||
{
|
||
return;
|
||
}
|
||
|
||
AvHOverviewMap& theOverviewMap = gHUD.GetOverviewMap();
|
||
|
||
AvHOverviewMap::DrawInfo theDrawInfo;
|
||
|
||
theDrawInfo.mX = XRES(m_OverviewData.insetWindowX + m_OverviewData.insetWindowWidth + 4);
|
||
theDrawInfo.mY = YRES(SPECTATOR_PANEL_HEIGHT + 4);
|
||
theDrawInfo.mWidth = ScreenWidth() - theDrawInfo.mX - XRES(4);
|
||
theDrawInfo.mHeight = ScreenHeight() - YRES(SPECTATOR_PANEL_HEIGHT + 4) - theDrawInfo.mY;
|
||
theDrawInfo.mZoomScale = 1.0f;
|
||
AvHMapExtents theMapExtents;
|
||
theOverviewMap.GetMapExtents(theMapExtents);
|
||
|
||
theDrawInfo.mFullScreen = true;
|
||
|
||
float worldWidth = theMapExtents.GetMaxMapX() - theMapExtents.GetMinMapX();
|
||
float worldHeight = theMapExtents.GetMaxMapY() - theMapExtents.GetMinMapY();
|
||
|
||
float xScale;
|
||
float yScale;
|
||
|
||
float aspect1 = worldWidth / worldHeight;
|
||
float aspect2 = ((float)theDrawInfo.mWidth) / theDrawInfo.mHeight;
|
||
|
||
if (aspect1 > aspect2)
|
||
{
|
||
xScale = 1;
|
||
yScale = 1 / aspect2;
|
||
}
|
||
else
|
||
{
|
||
xScale = aspect2;
|
||
yScale = 1;
|
||
}
|
||
|
||
float centerX = (theMapExtents.GetMinMapX() + theMapExtents.GetMaxMapX()) / 2;
|
||
float centerY = (theMapExtents.GetMinMapY() + theMapExtents.GetMaxMapY()) / 2;
|
||
|
||
theDrawInfo.mViewWorldMinX = centerX - worldWidth * xScale * 0.5;
|
||
theDrawInfo.mViewWorldMinY = centerY - worldHeight * yScale * 0.5;
|
||
theDrawInfo.mViewWorldMaxX = centerX + worldWidth * xScale * 0.5;
|
||
theDrawInfo.mViewWorldMaxY = centerY + worldHeight * yScale * 0.5;
|
||
|
||
if (m_hsprWhite != NULL)
|
||
{
|
||
|
||
float bgColor[] = { 0.1, 0.1, 0.1, 1 };
|
||
float borderColor[] = { 1, 1, 1, 1 };
|
||
|
||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||
gEngfuncs.pTriAPI->CullFace(TRI_NONE);
|
||
|
||
gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
|
||
float gammaScale = 1.0f/* / gHUD.GetGammaSlope()*/;
|
||
|
||
// Draw the background.
|
||
|
||
gEngfuncs.pTriAPI->Color4f(gammaScale * bgColor[0], gammaScale * bgColor[1], gammaScale * bgColor[2], bgColor[3]);
|
||
|
||
gEngfuncs.pTriAPI->Begin(TRI_QUADS);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
|
||
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
// Draw the overview map.
|
||
|
||
theOverviewMap.Draw(theDrawInfo);
|
||
|
||
// Draw the border on the overview map and the inset view.
|
||
|
||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||
gEngfuncs.pTriAPI->CullFace(TRI_NONE);
|
||
|
||
gEngfuncs.pTriAPI->SpriteTexture((struct model_s*)(gEngfuncs.GetSpritePointer(m_hsprWhite)), 0);
|
||
gEngfuncs.pTriAPI->Color4f(gammaScale * borderColor[0], gammaScale * borderColor[1], gammaScale * borderColor[2], borderColor[3]);
|
||
|
||
gEngfuncs.pTriAPI->Begin(TRI_LINES);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY + theDrawInfo.mHeight, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY + theDrawInfo.mHeight, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX + theDrawInfo.mWidth, theDrawInfo.mY, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(theDrawInfo.mX, theDrawInfo.mY, 1);
|
||
|
||
int insetX1 = XRES(m_OverviewData.insetWindowX);
|
||
int insetY1 = YRES(m_OverviewData.insetWindowY);
|
||
int insetX2 = insetX1 + XRES(m_OverviewData.insetWindowWidth);
|
||
int insetY2 = insetY1 + YRES(m_OverviewData.insetWindowHeight);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY1, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX2, insetY2, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
|
||
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY2, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f(insetX1, insetY1, 1);
|
||
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
#include "parsemsg.h"
|
||
void CHudSpectator::DirectorMessage( int iSize, void *pbuf )
|
||
{
|
||
float value;
|
||
char * string;
|
||
|
||
BEGIN_READ( pbuf, iSize );
|
||
|
||
int cmd = READ_BYTE();
|
||
|
||
switch ( cmd ) // director command byte
|
||
{
|
||
case DRC_CMD_START :
|
||
// now we have to do some things clientside, since the proxy doesn't know our mod
|
||
g_iPlayerClass = 0;
|
||
g_iTeamNumber = 0;
|
||
|
||
// fake a InitHUD & ResetHUD message
|
||
gHUD.MsgFunc_InitHUD(NULL,0, NULL);
|
||
gHUD.MsgFunc_ResetHUD(NULL, 0, NULL);
|
||
|
||
break;
|
||
|
||
case DRC_CMD_EVENT :
|
||
m_lastPrimaryObject = READ_WORD();
|
||
m_lastSecondaryObject = READ_WORD();
|
||
m_iObserverFlags = READ_LONG();
|
||
|
||
if ( m_autoDirector->value )
|
||
{
|
||
if ( (g_iUser2 != m_lastPrimaryObject) || (g_iUser3 != m_lastSecondaryObject) )
|
||
V_ResetChaseCam();
|
||
|
||
g_iUser2 = m_lastPrimaryObject;
|
||
g_iUser3 = m_lastSecondaryObject;
|
||
}
|
||
|
||
break;
|
||
|
||
case DRC_CMD_MODE :
|
||
if ( m_autoDirector->value )
|
||
{
|
||
SetMode( READ_BYTE());
|
||
}
|
||
break;
|
||
|
||
case DRC_CMD_CAMERA :
|
||
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;
|
||
}
|
||
break;
|
||
|
||
case DRC_CMD_MESSAGE:
|
||
{
|
||
client_textmessage_t * msg = &m_HUDMessages[m_lastHudMessage];
|
||
|
||
msg->effect = READ_BYTE(); // effect
|
||
|
||
UnpackRGB( (int&)msg->r1, (int&)msg->g1, (int&)msg->b1, READ_LONG() ); // color
|
||
msg->r2 = msg->r1;
|
||
msg->g2 = msg->g1;
|
||
msg->b2 = msg->b1;
|
||
msg->a2 = msg->a1 = 0xFF; // not transparent
|
||
|
||
msg->x = READ_FLOAT(); // x pos
|
||
msg->y = READ_FLOAT(); // y pos
|
||
|
||
msg->fadein = READ_FLOAT(); // fadein
|
||
msg->fadeout = READ_FLOAT(); // fadeout
|
||
msg->holdtime = READ_FLOAT(); // holdtime
|
||
msg->fxtime = READ_FLOAT(); // fxtime;
|
||
|
||
strncpy( m_HUDMessageText[m_lastHudMessage], READ_STRING(), 128 );
|
||
m_HUDMessageText[m_lastHudMessage][127]=0; // text
|
||
|
||
msg->pMessage = m_HUDMessageText[m_lastHudMessage];
|
||
msg->pName = "HUD_MESSAGE";
|
||
|
||
gHUD.m_Message.MessageAdd( msg->pName, gHUD.m_flTime);
|
||
|
||
m_lastHudMessage++;
|
||
m_lastHudMessage %= MAX_SPEC_HUD_MESSAGES;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case DRC_CMD_SOUND :
|
||
string = READ_STRING();
|
||
value = READ_FLOAT();
|
||
|
||
gEngfuncs.pEventAPI->EV_PlaySound(0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM );
|
||
|
||
break;
|
||
|
||
case DRC_CMD_TIMESCALE :
|
||
value = READ_FLOAT();
|
||
break;
|
||
|
||
|
||
|
||
case DRC_CMD_STATUS:
|
||
READ_LONG(); // total number of spectator slots
|
||
m_iSpectatorNumber = READ_LONG(); // total number of spectator
|
||
READ_WORD(); // total number of relay proxies
|
||
|
||
gViewPort->UpdateSpectatorPanel();
|
||
break;
|
||
|
||
case DRC_CMD_BANNER:
|
||
// gEngfuncs.Con_DPrintf("GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga
|
||
gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() );
|
||
gViewPort->UpdateSpectatorPanel();
|
||
break;
|
||
|
||
case DRC_CMD_FADE:
|
||
break;
|
||
|
||
case DRC_CMD_STUFFTEXT:
|
||
ClientCmd( READ_STRING() );
|
||
break;
|
||
|
||
default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd );
|
||
}
|
||
}
|
||
|
||
void CHudSpectator::FindNextPlayer(bool bReverse)
|
||
{
|
||
// MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching
|
||
// only a subset of the players. e.g. Make it check the target's team.
|
||
|
||
int iStart;
|
||
cl_entity_t * pEnt = NULL;
|
||
|
||
// if we are NOT in HLTV mode, spectator targets are set on server
|
||
if ( !gEngfuncs.IsSpectateOnly() )
|
||
{
|
||
char cmdstring[32];
|
||
// forward command to server
|
||
sprintf(cmdstring,"follownext %i",bReverse?1:0);
|
||
gEngfuncs.pfnServerCmd(cmdstring);
|
||
return;
|
||
}
|
||
|
||
if ( g_iUser2 )
|
||
iStart = g_iUser2;
|
||
else
|
||
iStart = 1;
|
||
|
||
g_iUser2 = 0;
|
||
|
||
int iCurrent = iStart;
|
||
|
||
int iDir = bReverse ? -1 : 1;
|
||
|
||
// make sure we have player info
|
||
gViewPort->GetAllPlayersInfo();
|
||
|
||
|
||
do
|
||
{
|
||
iCurrent += iDir;
|
||
|
||
// Loop through the clients
|
||
if (iCurrent > MAX_PLAYERS)
|
||
iCurrent = 1;
|
||
if (iCurrent < 1)
|
||
iCurrent = MAX_PLAYERS;
|
||
|
||
pEnt = gEngfuncs.GetEntityByIndex( iCurrent );
|
||
|
||
if ( !IsActivePlayer( pEnt ) )
|
||
continue;
|
||
|
||
// MOD AUTHORS: Add checks on target here.
|
||
|
||
g_iUser2 = iCurrent;
|
||
break;
|
||
|
||
} while ( iCurrent != iStart );
|
||
|
||
// Did we find a target?
|
||
if ( !g_iUser2 )
|
||
{
|
||
gEngfuncs.Con_DPrintf( "No observer targets.\n" );
|
||
// take save camera position
|
||
VectorCopy(m_cameraOrigin, vJumpOrigin);
|
||
VectorCopy(m_cameraAngles, vJumpAngles);
|
||
}
|
||
else
|
||
{
|
||
// use new entity position for roaming
|
||
VectorCopy ( pEnt->origin, vJumpOrigin );
|
||
VectorCopy ( pEnt->angles, vJumpAngles );
|
||
}
|
||
iJumpSpectator = 1;
|
||
}
|
||
|
||
void CHudSpectator::HandleButtonsDown( int ButtonPressed )
|
||
{
|
||
if ( !gViewPort )
|
||
return;
|
||
|
||
//Not in intermission.
|
||
if ( gHUD.m_iIntermission )
|
||
return;
|
||
|
||
if ( !g_iUser1 )
|
||
return; // dont do anything if not in spectator mode
|
||
|
||
// don't handle buttons during normal demo playback
|
||
if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
|
||
return;
|
||
|
||
int theNewMainMode = g_iUser1;
|
||
|
||
// Crouch toggles the overview mode
|
||
if (gHUD.GetIsNSMode() && ButtonPressed & IN_DUCK)
|
||
{
|
||
bool theInOverviewMode = gHUD.m_Spectator.IsInOverviewMode();
|
||
gHUD.m_Spectator.SetOverviewMode(!theInOverviewMode);
|
||
}
|
||
|
||
// Jump changes spectator modes
|
||
if ( ButtonPressed & IN_JUMP )
|
||
{
|
||
theNewMainMode++;
|
||
|
||
AvHPlayMode CurrPlayMode = gHUD.GetPlayMode();
|
||
|
||
float FreeSpecMode = gHUD.GetServerVariableFloat(kvFreeSpectatorMode);
|
||
if (FreeSpecMode == 0 || (FreeSpecMode == 1 && gHUD.GetPlayMode() != PLAYMODE_OBSERVER))
|
||
{
|
||
while (theNewMainMode == OBS_CHASE_FREE || theNewMainMode == OBS_ROAMING)
|
||
{
|
||
theNewMainMode++;
|
||
}
|
||
}
|
||
|
||
if (theNewMainMode > OBS_IN_EYE)
|
||
{
|
||
theNewMainMode = OBS_CHASE_LOCKED;
|
||
}
|
||
|
||
gHUD.m_Spectator.SetMode(theNewMainMode);
|
||
}
|
||
|
||
//g_iUser1 = theNewMainMode;
|
||
|
||
// Attack moves to the next player
|
||
if (g_iUser1 != OBS_ROAMING && ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
|
||
{
|
||
FindNextPlayer( (ButtonPressed & IN_MOVELEFT) ? true:false );
|
||
|
||
// if ( g_iUser1 == OBS_ROAMING )
|
||
// {
|
||
// gEngfuncs.SetViewAngles( vJumpAngles );
|
||
// iJumpSpectator = 1;
|
||
//
|
||
// }
|
||
|
||
// lease directed mode if player want to see another player
|
||
m_autoDirector->value = 0.0f;
|
||
}
|
||
|
||
/*
|
||
double time = gEngfuncs.GetClientTime();
|
||
|
||
int newMainMode = g_iUser1;
|
||
int newInsetMode = m_pip->value;
|
||
|
||
// gEngfuncs.Con_Printf(" HandleButtons:%i\n", ButtonPressed );
|
||
if ( !gViewPort )
|
||
return;
|
||
|
||
//Not in intermission.
|
||
if ( gHUD.m_iIntermission )
|
||
return;
|
||
|
||
if ( !g_iUser1 )
|
||
return; // dont do anything if not in spectator mode
|
||
|
||
// don't handle buttons during normal demo playback
|
||
if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() )
|
||
return;
|
||
// Slow down mouse clicks.
|
||
if ( m_flNextObserverInput > time )
|
||
return;
|
||
|
||
// enable spectator screen
|
||
if ( ButtonPressed & IN_DUCK )
|
||
{
|
||
gViewPort->m_pSpectatorPanel->ShowMenu(!gViewPort->m_pSpectatorPanel->m_menuVisible);
|
||
}
|
||
|
||
// 'Use' changes inset window mode
|
||
if ( ButtonPressed & IN_USE )
|
||
{
|
||
newInsetMode = ToggleInset(true);
|
||
}
|
||
|
||
// if not in HLTV mode, buttons are handled server side
|
||
if ( gEngfuncs.IsSpectateOnly() )
|
||
{
|
||
// changing target or chase mode not in overviewmode without inset window
|
||
|
||
// Jump changes main window modes
|
||
if ( ButtonPressed & IN_JUMP )
|
||
{
|
||
if ( g_iUser1 == OBS_CHASE_LOCKED )
|
||
newMainMode = OBS_CHASE_FREE;
|
||
|
||
else if ( g_iUser1 == OBS_CHASE_FREE )
|
||
newMainMode = OBS_IN_EYE;
|
||
|
||
else if ( g_iUser1 == OBS_IN_EYE )
|
||
newMainMode = OBS_ROAMING;
|
||
|
||
else if ( g_iUser1 == OBS_ROAMING )
|
||
newMainMode = OBS_MAP_FREE;
|
||
|
||
else if ( g_iUser1 == OBS_MAP_FREE )
|
||
newMainMode = OBS_MAP_CHASE;
|
||
|
||
else
|
||
newMainMode = OBS_CHASE_FREE; // don't use OBS_CHASE_LOCKED anymore
|
||
}
|
||
|
||
// Attack moves to the next player
|
||
if ( ButtonPressed & (IN_ATTACK | IN_ATTACK2) )
|
||
{
|
||
FindNextPlayer( (ButtonPressed & IN_ATTACK2) ? true:false );
|
||
|
||
if ( g_iUser1 == OBS_ROAMING )
|
||
{
|
||
gEngfuncs.SetViewAngles( vJumpAngles );
|
||
iJumpSpectator = 1;
|
||
|
||
}
|
||
// lease directed mode if player want to see another player
|
||
m_autoDirector->value = 0.0f;
|
||
}
|
||
}
|
||
|
||
SetModes(newMainMode, newInsetMode);
|
||
|
||
if ( g_iUser1 == OBS_MAP_FREE )
|
||
{
|
||
if ( ButtonPressed & IN_FORWARD )
|
||
m_zoomDelta = 0.01f;
|
||
|
||
if ( ButtonPressed & IN_BACK )
|
||
m_zoomDelta = -0.01f;
|
||
|
||
if ( ButtonPressed & IN_MOVELEFT )
|
||
m_moveDelta = -12.0f;
|
||
|
||
if ( ButtonPressed & IN_MOVERIGHT )
|
||
m_moveDelta = 12.0f;
|
||
}
|
||
|
||
m_flNextObserverInput = time + 0.2;
|
||
*/
|
||
|
||
}
|
||
|
||
void CHudSpectator::HandleButtonsUp( int ButtonPressed )
|
||
{
|
||
if ( !gViewPort )
|
||
return;
|
||
|
||
if ( !gViewPort->m_pSpectatorPanel->isVisible() )
|
||
return; // dont do anything if not in spectator mode
|
||
|
||
if ( ButtonPressed & (IN_FORWARD | IN_BACK) )
|
||
m_zoomDelta = 0.0f;
|
||
|
||
if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) )
|
||
m_moveDelta = 0.0f;
|
||
}
|
||
|
||
void CHudSpectator::SetMode(int iNewMainMode)
|
||
{
|
||
int NewMode = iNewMainMode;
|
||
|
||
if (NewMode == OBS_CHASE_FREE || NewMode == OBS_ROAMING)
|
||
{
|
||
float FreeSpecMode = gHUD.GetServerVariableFloat(kvFreeSpectatorMode);
|
||
if ((FreeSpecMode == 0 || (FreeSpecMode == 1.0f && gHUD.GetPlayMode() != PLAYMODE_OBSERVER)) && !gEngfuncs.IsSpectateOnly())
|
||
{
|
||
if (g_iUser1 != OBS_CHASE_FREE && g_iUser1 != OBS_ROAMING)
|
||
{
|
||
NewMode = g_iUser1;
|
||
}
|
||
else
|
||
{
|
||
NewMode = OBS_IN_EYE;
|
||
}
|
||
}
|
||
}
|
||
|
||
// if value == -1 keep old value
|
||
if (NewMode == -1 )
|
||
NewMode = g_iUser1;
|
||
|
||
// main modes ettings will override inset window settings
|
||
if (NewMode != g_iUser1 )
|
||
{
|
||
// if we are NOT in HLTV mode, main spectator mode is set on server
|
||
if ( !gEngfuncs.IsSpectateOnly() )
|
||
{
|
||
char cmdstring[32];
|
||
// forward command to server
|
||
sprintf(cmdstring,"specmode %i", NewMode);
|
||
gEngfuncs.pfnServerCmd(cmdstring);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
if ( !g_iUser2 && (NewMode != OBS_ROAMING ) ) // make sure we have a target
|
||
{
|
||
// choose last Director object if still available
|
||
if ( IsActivePlayer( gEngfuncs.GetEntityByIndex( m_lastPrimaryObject ) ) )
|
||
{
|
||
g_iUser2 = m_lastPrimaryObject;
|
||
g_iUser3 = m_lastSecondaryObject;
|
||
}
|
||
else
|
||
{
|
||
FindNextPlayer(false); // find any target
|
||
}
|
||
}
|
||
|
||
switch (NewMode)
|
||
{
|
||
case OBS_CHASE_LOCKED:
|
||
g_iUser1 = OBS_CHASE_LOCKED;
|
||
break;
|
||
|
||
case OBS_CHASE_FREE:
|
||
g_iUser1 = OBS_CHASE_FREE;
|
||
break;
|
||
|
||
case OBS_ROAMING : // jump to current vJumpOrigin/angle
|
||
g_iUser1 = OBS_ROAMING;
|
||
if ( g_iUser2 )
|
||
{
|
||
V_GetChasePos( g_iUser2, v_cl_angles, vJumpOrigin, vJumpAngles );
|
||
gEngfuncs.SetViewAngles( vJumpAngles );
|
||
iJumpSpectator = 1;
|
||
}
|
||
break;
|
||
|
||
case OBS_IN_EYE:
|
||
g_iUser1 = OBS_IN_EYE;
|
||
break;
|
||
|
||
/*
|
||
case OBS_MAP_FREE : g_iUser1 = OBS_MAP_FREE;
|
||
// reset user values
|
||
m_mapZoom = m_OverviewData.zoom;
|
||
m_mapOrigin = m_OverviewData.origin;
|
||
break;
|
||
|
||
case OBS_MAP_CHASE : g_iUser1 = OBS_MAP_CHASE;
|
||
// reset user values
|
||
m_mapZoom = m_OverviewData.zoom;
|
||
m_mapOrigin = m_OverviewData.origin;
|
||
break;
|
||
*/
|
||
}
|
||
|
||
if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) )
|
||
{
|
||
m_crosshairRect.left = 24;
|
||
m_crosshairRect.top = 0;
|
||
m_crosshairRect.right = 48;
|
||
m_crosshairRect.bottom = 24;
|
||
|
||
gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
|
||
|
||
gWR.SetWeaponConfig(nullptr, 1);
|
||
}
|
||
else
|
||
{
|
||
memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
|
||
gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
|
||
|
||
gWR.SetWeaponConfig(nullptr, -1);
|
||
}
|
||
|
||
//char string[128];
|
||
//sprintf(string, "#Spec_Mode%d", g_iUser1 );
|
||
//sprintf(string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string ));
|
||
//gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string );
|
||
}
|
||
}
|
||
|
||
gViewPort->UpdateSpectatorPanel();
|
||
}
|
||
|
||
bool CHudSpectator::IsActivePlayer(cl_entity_t * ent)
|
||
{
|
||
return ( ent &&
|
||
ent->player &&
|
||
ent->curstate.solid != SOLID_NOT &&
|
||
ent != gEngfuncs.GetLocalPlayer() &&
|
||
g_PlayerInfoList[ent->index].name != NULL
|
||
);
|
||
}
|
||
|
||
|
||
bool CHudSpectator::ParseOverviewFile( )
|
||
{
|
||
//char filename[255];
|
||
//char levelname[255];
|
||
//char token[1024];
|
||
//float height;
|
||
|
||
char *pfile = NULL;
|
||
|
||
memset( &m_OverviewData, 0, sizeof(m_OverviewData));
|
||
|
||
// fill in standrd values
|
||
m_OverviewData.insetWindowX = 4; // upper left corner
|
||
m_OverviewData.insetWindowY = 4 + SPECTATOR_PANEL_HEIGHT;
|
||
m_OverviewData.insetWindowHeight = 180;
|
||
m_OverviewData.insetWindowWidth = 240;
|
||
m_OverviewData.origin[0] = 0.0f;
|
||
m_OverviewData.origin[1] = 0.0f;
|
||
m_OverviewData.origin[2] = 0.0f;
|
||
m_OverviewData.zoom = 1.0f;
|
||
m_OverviewData.layers = 0;
|
||
m_OverviewData.layersHeights[0] = 0.0f;
|
||
strcpy( m_OverviewData.map, gEngfuncs.pfnGetLevelName() );
|
||
|
||
if ( strlen( m_OverviewData.map ) == 0 )
|
||
return false; // not active yet
|
||
|
||
/*
|
||
strcpy(levelname, m_OverviewData.map + 5);
|
||
levelname[strlen(levelname)-4] = 0;
|
||
|
||
sprintf(filename, "overviews/%s.txt", levelname );
|
||
|
||
pfile = (char *)gEngfuncs.COM_LoadFile( filename, 5, NULL);
|
||
|
||
if (!pfile)
|
||
{
|
||
gEngfuncs.Con_Printf("Couldn't open file %s. Using default values for overiew mode.\n", filename );
|
||
return false;
|
||
}
|
||
|
||
while (true)
|
||
{
|
||
pfile = gEngfuncs.COM_ParseFile(pfile, token);
|
||
|
||
if (!pfile)
|
||
break;
|
||
|
||
if ( !stricmp( token, "global" ) )
|
||
{
|
||
// parse the global data
|
||
pfile = gEngfuncs.COM_ParseFile(pfile, token);
|
||
if ( stricmp( token, "{" ) )
|
||
{
|
||
gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
|
||
return false;
|
||
}
|
||
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
|
||
while (stricmp( token, "}") )
|
||
{
|
||
if ( !stricmp( token, "zoom" ) )
|
||
{
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
m_OverviewData.zoom = atof( token );
|
||
}
|
||
else if ( !stricmp( token, "origin" ) )
|
||
{
|
||
pfile = gEngfuncs.COM_ParseFile(pfile, token);
|
||
m_OverviewData.origin[0] = atof( token );
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
m_OverviewData.origin[1] = atof( token );
|
||
pfile = gEngfuncs.COM_ParseFile(pfile, token);
|
||
m_OverviewData.origin[2] = atof( token );
|
||
}
|
||
else if ( !stricmp( token, "rotated" ) )
|
||
{
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
m_OverviewData.rotated = atoi( token );
|
||
}
|
||
else if ( !stricmp( token, "inset" ) )
|
||
{
|
||
|
||
// Removed by mmcguire.
|
||
// This isn't supported anymore.
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
//m_OverviewData.insetWindowX = atof( token );
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
//m_OverviewData.insetWindowY = atof( token );
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
//m_OverviewData.insetWindowWidth = atof( token );
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
//m_OverviewData.insetWindowHeight = atof( token );
|
||
|
||
}
|
||
else
|
||
{
|
||
gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
|
||
return false;
|
||
}
|
||
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
|
||
|
||
}
|
||
}
|
||
else if ( !stricmp( token, "layer" ) )
|
||
{
|
||
// parse a layer data
|
||
|
||
if ( m_OverviewData.layers == OVERVIEW_MAX_LAYERS )
|
||
{
|
||
gEngfuncs.Con_Printf("Error parsing overview file %s. ( too many layers )\n", filename );
|
||
return false;
|
||
}
|
||
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
|
||
|
||
if ( stricmp( token, "{" ) )
|
||
{
|
||
gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename );
|
||
return false;
|
||
}
|
||
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
|
||
while (stricmp( token, "}") )
|
||
{
|
||
if ( !stricmp( token, "image" ) )
|
||
{
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
strcpy(m_OverviewData.layersImages[ m_OverviewData.layers ], token);
|
||
|
||
|
||
}
|
||
else if ( !stricmp( token, "height" ) )
|
||
{
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token);
|
||
height = atof(token);
|
||
m_OverviewData.layersHeights[ m_OverviewData.layers ] = height;
|
||
}
|
||
else
|
||
{
|
||
gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token );
|
||
return false;
|
||
}
|
||
|
||
pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token
|
||
}
|
||
|
||
m_OverviewData.layers++;
|
||
|
||
}
|
||
}
|
||
|
||
gEngfuncs.COM_FreeFile( pfile );
|
||
*/
|
||
|
||
m_mapZoom = m_OverviewData.zoom;
|
||
m_mapOrigin = m_OverviewData.origin;
|
||
|
||
return true;
|
||
|
||
}
|
||
|
||
void CHudSpectator::LoadMapSprites()
|
||
{
|
||
// right now only support for one map layer
|
||
if (m_OverviewData.layers > 0 )
|
||
{
|
||
m_MapSprite = gEngfuncs.LoadMapSprite( m_OverviewData.layersImages[0] );
|
||
}
|
||
else
|
||
m_MapSprite = NULL; // the standard "unkown map" sprite will be used instead
|
||
}
|
||
|
||
void CHudSpectator::DrawOverviewLayer()
|
||
{
|
||
float screenaspect, xs, ys, xStep, yStep, x,y,z;
|
||
int ix,iy,i,xTiles,yTiles,frame;
|
||
|
||
qboolean hasMapImage = m_MapSprite?TRUE:FALSE;
|
||
model_t * dummySprite = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprUnkownMap);
|
||
|
||
if ( hasMapImage)
|
||
{
|
||
i = m_MapSprite->numframes / (4*3);
|
||
i = sqrt((float)i);
|
||
xTiles = i*4;
|
||
yTiles = i*3;
|
||
}
|
||
else
|
||
{
|
||
xTiles = 8;
|
||
yTiles = 6;
|
||
}
|
||
|
||
|
||
screenaspect = 4.0f/3.0f;
|
||
|
||
|
||
xs = m_OverviewData.origin[0];
|
||
ys = m_OverviewData.origin[1];
|
||
z = ( 90.0f - v_angles[0] ) / 90.0f;
|
||
z *= m_OverviewData.layersHeights[0]; // gOverviewData.z_min - 32;
|
||
|
||
// i = r_overviewTexture + ( layer*OVERVIEW_X_TILES*OVERVIEW_Y_TILES );
|
||
|
||
gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
|
||
gEngfuncs.pTriAPI->CullFace( TRI_NONE );
|
||
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
|
||
|
||
frame = 0;
|
||
|
||
|
||
// rotated view ?
|
||
if ( m_OverviewData.rotated )
|
||
{
|
||
xStep = (2*4096.0f / m_OverviewData.zoom ) / xTiles;
|
||
yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
|
||
|
||
y = ys + (4096.0f / (m_OverviewData.zoom * screenaspect));
|
||
|
||
for (iy = 0; iy < yTiles; iy++)
|
||
{
|
||
x = xs - (4096.0f / (m_OverviewData.zoom));
|
||
|
||
for (ix = 0; ix < xTiles; ix++)
|
||
{
|
||
if (hasMapImage)
|
||
gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
|
||
else
|
||
gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
|
||
|
||
gEngfuncs.pTriAPI->Begin( TRI_QUADS );
|
||
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x, y, z);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
frame++;
|
||
x+= xStep;
|
||
}
|
||
|
||
y+=yStep;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
xStep = -(2*4096.0f / m_OverviewData.zoom ) / xTiles;
|
||
yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles;
|
||
|
||
|
||
x = xs + (4096.0f / (m_OverviewData.zoom * screenaspect ));
|
||
|
||
|
||
|
||
for (ix = 0; ix < yTiles; ix++)
|
||
{
|
||
|
||
y = ys + (4096.0f / (m_OverviewData.zoom));
|
||
|
||
for (iy = 0; iy < xTiles; iy++)
|
||
{
|
||
if (hasMapImage)
|
||
gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame );
|
||
else
|
||
gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 );
|
||
|
||
gEngfuncs.pTriAPI->Begin( TRI_QUADS );
|
||
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x, y, z);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z);
|
||
gEngfuncs.pTriAPI->End();
|
||
|
||
frame++;
|
||
|
||
y+=yStep;
|
||
}
|
||
|
||
x+= xStep;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
void CHudSpectator::DrawOverviewEntities()
|
||
{
|
||
/*
|
||
int i,ir,ig,ib;
|
||
struct model_s *hSpriteModel;
|
||
vec3_t origin, angles, point, forward, right, left, up, world, screen, offset;
|
||
float x,y,z, r,g,b, sizeScale = 4.0f;
|
||
cl_entity_t * ent;
|
||
float rmatrix[3][4]; // transformation matrix
|
||
|
||
float zScale = (90.0f - v_angles[0] ) / 90.0f;
|
||
|
||
|
||
z = m_OverviewData.layersHeights[0] * zScale;
|
||
// get yellow/brown HUD color
|
||
//UnpackRGB(ir,ig,ib, RGB_YELLOWISH);
|
||
gHUD.GetPrimaryHudColor(ir, ig, ib);
|
||
r = (float)ir/255.0f;
|
||
g = (float)ig/255.0f;
|
||
b = (float)ib/255.0f;
|
||
|
||
gEngfuncs.pTriAPI->CullFace( TRI_NONE );
|
||
|
||
for (i=0; i < MAX_PLAYERS; i++ )
|
||
m_vPlayerPos[i][2] = -1; // mark as invisible
|
||
|
||
// draw all players
|
||
|
||
float depthOffset = 0;
|
||
|
||
for (i=MAX_OVERVIEW_ENTITIES - 1; i >= 0; i--)
|
||
{
|
||
if ( !m_OverviewEntities[i].hSprite )
|
||
continue;
|
||
|
||
hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_OverviewEntities[i].hSprite );
|
||
ent = m_OverviewEntities[i].entity;
|
||
|
||
int theSpriteFrame = m_OverviewEntities[i].mFrame;
|
||
gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, theSpriteFrame);
|
||
|
||
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd);
|
||
|
||
// see R_DrawSpriteModel
|
||
// draws players sprite
|
||
|
||
AngleVectors(ent->angles, right, up, NULL );
|
||
|
||
VectorCopy(ent->origin,origin);
|
||
|
||
// Set origin of blip to just above map height, so blips are all drawn on map
|
||
origin.z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight + depthOffset;
|
||
|
||
gEngfuncs.pTriAPI->Begin( TRI_QUADS );
|
||
|
||
float gammaSlope = gHUD.GetGammaSlope();
|
||
|
||
gEngfuncs.pTriAPI->Color4f(
|
||
m_OverviewEntities[i].mColorR / gammaSlope,
|
||
m_OverviewEntities[i].mColorG / gammaSlope,
|
||
m_OverviewEntities[i].mColorB / gammaSlope,
|
||
1);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f (1, 0);
|
||
VectorMA (origin, 16.0f * sizeScale, up, point);
|
||
VectorMA (point, 16.0f * sizeScale, right, point);
|
||
point[2] *= zScale;
|
||
gEngfuncs.pTriAPI->Vertex3fv (point);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f (0, 0);
|
||
|
||
VectorMA (origin, 16.0f * sizeScale, up, point);
|
||
VectorMA (point, -16.0f * sizeScale, right, point);
|
||
point[2] *= zScale;
|
||
gEngfuncs.pTriAPI->Vertex3fv (point);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f (0,1);
|
||
VectorMA (origin, -16.0f * sizeScale, up, point);
|
||
VectorMA (point, -16.0f * sizeScale, right, point);
|
||
point[2] *= zScale;
|
||
gEngfuncs.pTriAPI->Vertex3fv (point);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f (1,1);
|
||
VectorMA (origin, -16.0f * sizeScale, up, point);
|
||
VectorMA (point, 16.0f * sizeScale, right, point);
|
||
point[2] *= zScale;
|
||
gEngfuncs.pTriAPI->Vertex3fv (point);
|
||
|
||
gEngfuncs.pTriAPI->End ();
|
||
|
||
|
||
if ( !ent->player)
|
||
continue;
|
||
// draw line under player icons
|
||
origin[2] *= zScale;
|
||
|
||
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
|
||
|
||
hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprBeam );
|
||
gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
|
||
|
||
gEngfuncs.pTriAPI->Color4f(r, g, b, 0.3);
|
||
|
||
gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
|
||
gEngfuncs.pTriAPI->TexCoord2f (1, 0);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4, origin[2]-zScale);
|
||
gEngfuncs.pTriAPI->TexCoord2f (0, 0);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4, origin[2]-zScale);
|
||
gEngfuncs.pTriAPI->TexCoord2f (0, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4,z);
|
||
gEngfuncs.pTriAPI->TexCoord2f (1, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4,z);
|
||
gEngfuncs.pTriAPI->End ();
|
||
|
||
gEngfuncs.pTriAPI->Begin ( TRI_QUADS );
|
||
gEngfuncs.pTriAPI->TexCoord2f (1, 0);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4, origin[2]-zScale);
|
||
gEngfuncs.pTriAPI->TexCoord2f (0, 0);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4, origin[2]-zScale);
|
||
gEngfuncs.pTriAPI->TexCoord2f (0, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4,z);
|
||
gEngfuncs.pTriAPI->TexCoord2f (1, 1);
|
||
gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4,z);
|
||
gEngfuncs.pTriAPI->End ();
|
||
|
||
// calculate screen position for name and infromation in hud::draw()
|
||
if ( gEngfuncs.pTriAPI->WorldToScreen(origin,screen) )
|
||
continue; // object is behind viewer
|
||
|
||
screen[0] = XPROJECT(screen[0]);
|
||
screen[1] = YPROJECT(screen[1]);
|
||
screen[2] = 0.0f;
|
||
|
||
// calculate some offset under the icon
|
||
origin[0]+=32.0f;
|
||
origin[1]+=32.0f;
|
||
|
||
gEngfuncs.pTriAPI->WorldToScreen(origin,offset);
|
||
|
||
offset[0] = XPROJECT(offset[0]);
|
||
offset[1] = YPROJECT(offset[1]);
|
||
offset[2] = 0.0f;
|
||
|
||
VectorSubtract(offset, screen, offset );
|
||
|
||
int playerNum = ent->index - 1;
|
||
|
||
m_vPlayerPos[playerNum][0] = screen[0];
|
||
m_vPlayerPos[playerNum][1] = screen[1] + Length(offset);
|
||
m_vPlayerPos[playerNum][2] = 1; // mark player as visible
|
||
|
||
|
||
}
|
||
|
||
if ( !m_pip || !m_drawcone->value )
|
||
return;
|
||
|
||
// get current camera position and angle
|
||
|
||
if ( m_pip == INSET_IN_EYE || g_iUser1 == OBS_IN_EYE )
|
||
{
|
||
V_GetInEyePos( g_iUser2, origin, angles );
|
||
}
|
||
else if ( m_pip == INSET_CHASE_FREE || g_iUser1 == OBS_CHASE_FREE )
|
||
{
|
||
V_GetChasePos( g_iUser2, v_cl_angles, origin, angles );
|
||
}
|
||
else if ( g_iUser1 == OBS_ROAMING )
|
||
{
|
||
VectorCopy( v_sim_org, origin );
|
||
VectorCopy( v_cl_angles, angles );
|
||
}
|
||
else
|
||
V_GetChasePos( g_iUser2, NULL, origin, angles );
|
||
|
||
|
||
// draw camera sprite
|
||
|
||
x = origin[0];
|
||
y = origin[1];
|
||
z = origin[2];
|
||
|
||
// Set origin of cone to just above map height, so blips are all drawn on map
|
||
z = m_OverviewData.layersHeights[0] + kOverviewEntityZHeight;
|
||
|
||
angles[0] = 0; // always show horizontal camera sprite
|
||
|
||
hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprCamera );
|
||
gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd );
|
||
gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 );
|
||
|
||
|
||
gEngfuncs.pTriAPI->Color4f( r, g, b, 1.0 );
|
||
|
||
AngleVectors(angles, forward, NULL, NULL );
|
||
VectorScale (forward, 512.0f, forward);
|
||
|
||
offset[0] = 0.0f;
|
||
offset[1] = 45.0f;
|
||
offset[2] = 0.0f;
|
||
|
||
AngleMatrix(offset, rmatrix );
|
||
VectorTransform(forward, rmatrix , right );
|
||
|
||
offset[1]= -45.0f;
|
||
AngleMatrix(offset, rmatrix );
|
||
VectorTransform(forward, rmatrix , left );
|
||
|
||
gEngfuncs.pTriAPI->Begin (TRI_TRIANGLES);
|
||
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x+right[0], y+right[1], (z+right[2]) * zScale);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x, y, z * zScale);
|
||
|
||
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
|
||
gEngfuncs.pTriAPI->Vertex3f (x+left[0], y+left[1], (z+left[2]) * zScale);
|
||
gEngfuncs.pTriAPI->End ();
|
||
*/
|
||
|
||
}
|
||
|
||
|
||
|
||
void CHudSpectator::DrawOverview()
|
||
{
|
||
/*
|
||
// draw only in sepctator mode
|
||
if ( !g_iUser1 )
|
||
return;
|
||
|
||
// Only draw the overview if Map Mode is selected for this view
|
||
if ( m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) ) )
|
||
return;
|
||
|
||
if ( m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE )
|
||
return;
|
||
|
||
DrawOverviewLayer();
|
||
DrawOverviewEntities();
|
||
CheckOverviewEntities();
|
||
*/
|
||
|
||
}
|
||
|
||
|
||
|
||
void CHudSpectator::CheckOverviewEntities()
|
||
{
|
||
double time = gEngfuncs.GetClientTime();
|
||
|
||
// removes old entities from list
|
||
for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
|
||
{
|
||
// remove entity from list if it is too old
|
||
if ( m_OverviewEntities[i].killTime < time )
|
||
{
|
||
memset( &m_OverviewEntities[i], 0, sizeof (overviewEntity_t) );
|
||
}
|
||
}
|
||
}
|
||
|
||
bool CHudSpectator::AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname)
|
||
{
|
||
AVHHSPRITE hSprite = 0;
|
||
double duration = -1.0f; // duration -1 means show it only this frame;
|
||
int theFrame = 0;
|
||
bool theSuccess = false;
|
||
int theRenderMode;
|
||
|
||
if ( ent )
|
||
{
|
||
|
||
if (ent->curstate.solid != SOLID_NOT)
|
||
{
|
||
gHUD.GetSpriteForUser3(AvHUser3(ent->curstate.iuser3), hSprite, theFrame, theRenderMode);
|
||
}
|
||
|
||
/*
|
||
if ( type == ET_PLAYER )
|
||
{
|
||
if ( ent->curstate.solid != SOLID_NOT)
|
||
{
|
||
int thePlayerClass = g_PlayerExtraInfo[ent->index].playerclass;
|
||
switch(thePlayerClass)
|
||
{
|
||
case PLAYERCLASS_ALIVE_MARINE:
|
||
hSprite = this->m_hsprPlayerMarine;
|
||
theFrame = 0;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_HEAVY_MARINE:
|
||
hSprite = this->m_hsprPlayerMarine;
|
||
theFrame = 1;
|
||
break;
|
||
case PLAYERCLASS_COMMANDER:
|
||
hSprite = this->m_hsprPlayerMarine;
|
||
theFrame = 2;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_LEVEL1:
|
||
hSprite = this->m_hsprPlayerAlien;
|
||
theFrame = 0;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_LEVEL2:
|
||
hSprite = this->m_hsprPlayerAlien;
|
||
theFrame = 1;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_LEVEL3:
|
||
hSprite = this->m_hsprPlayerAlien;
|
||
theFrame = 2;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_LEVEL4:
|
||
hSprite = this->m_hsprPlayerAlien;
|
||
theFrame = 3;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_LEVEL5:
|
||
hSprite = this->m_hsprPlayerAlien;
|
||
theFrame = 4;
|
||
break;
|
||
case PLAYERCLASS_ALIVE_GESTATING:
|
||
hSprite = this->m_hsprPlayerAlien;
|
||
theFrame = 5;
|
||
break;
|
||
|
||
case PLAYERCLASS_ALIVE_DIGESTING:
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// it's an spectator
|
||
}
|
||
}
|
||
else if (type == ET_NORMAL)
|
||
{
|
||
// Now help icons
|
||
if(hSprite == 0)
|
||
{
|
||
AvHUser3 theUser3 = AvHUser3(ent->curstate.iuser3);
|
||
theFrame = gHUD.GetHelpIconFrameFromUser3(theUser3);
|
||
if(theFrame != -1)
|
||
{
|
||
hSprite = gHUD.GetHelpSprite();
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
}
|
||
|
||
if(hSprite > 0)
|
||
{
|
||
|
||
int theTeam = ent->curstate.team;
|
||
|
||
float theR = kFTeamColors[theTeam][0];
|
||
float theG = kFTeamColors[theTeam][1];
|
||
float theB = kFTeamColors[theTeam][2];
|
||
|
||
theSuccess = AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration, theFrame, theRenderMode, theR, theG, theB);
|
||
|
||
}
|
||
|
||
return theSuccess;
|
||
}
|
||
|
||
void CHudSpectator::DeathMessage(int victim)
|
||
{
|
||
// find out where the victim is
|
||
cl_entity_t *pl = gEngfuncs.GetEntityByIndex(victim);
|
||
|
||
if (pl && pl->player)
|
||
AddOverviewEntityToList(m_hsprPlayerDead, pl, gEngfuncs.GetClientTime() + 2.0f, 0, kRenderTransTexture, 1, 1, 1);
|
||
}
|
||
|
||
bool CHudSpectator::AddOverviewEntityToList(AVHHSPRITE sprite, cl_entity_t *ent, double killTime, int inFrame, int inRenderMode, float r, float g, float b)
|
||
{
|
||
for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ )
|
||
{
|
||
// find empty entity slot
|
||
if ( m_OverviewEntities[i].entity == NULL)
|
||
{
|
||
m_OverviewEntities[i].entity = ent;
|
||
m_OverviewEntities[i].hSprite = sprite;
|
||
m_OverviewEntities[i].killTime = killTime;
|
||
m_OverviewEntities[i].mFrame = inFrame;
|
||
m_OverviewEntities[i].mRenderMode = inRenderMode;
|
||
m_OverviewEntities[i].mColorR = r;
|
||
m_OverviewEntities[i].mColorG = g;
|
||
m_OverviewEntities[i].mColorB = b;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false; // maximum overview entities reached
|
||
}
|
||
void CHudSpectator::CheckSettings()
|
||
{
|
||
// disallow same inset mode as main mode:
|
||
|
||
//m_pip->value = floor(m_pip->value);
|
||
|
||
// Removed by mmcguire.
|
||
/*
|
||
if ( ( g_iUser1 < OBS_MAP_FREE ) && ( m_pip->value == INSET_CHASE_LOCKED || m_pip->value == INSET_IN_EYE ) )
|
||
{
|
||
// otherwise both would show in World picures
|
||
m_pip->value = INSET_OFF;
|
||
}
|
||
|
||
// disble in intermission screen
|
||
if ( gHUD.m_iIntermission )
|
||
m_pip->value = INSET_OFF;
|
||
*/
|
||
|
||
// check chat mode
|
||
if ( m_chatEnabled != (gHUD.m_SayText.m_HUD_saytext->value!=0) )
|
||
{
|
||
// hud_saytext changed
|
||
m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0);
|
||
|
||
if ( gEngfuncs.IsSpectateOnly() )
|
||
{
|
||
// tell proxy our new chat mode
|
||
char chatcmd[32];
|
||
sprintf(chatcmd, "ignoremsg %i", m_chatEnabled?0:1 );
|
||
gEngfuncs.pfnServerCmd(chatcmd);
|
||
}
|
||
}
|
||
|
||
// HL/TFC has no oberserver corsshair, so set it client side
|
||
if ( g_iUser1 == OBS_IN_EYE )
|
||
{
|
||
m_crosshairRect.left = 24;
|
||
m_crosshairRect.top = 0;
|
||
m_crosshairRect.right = 48;
|
||
m_crosshairRect.bottom = 24;
|
||
|
||
gHUD.SetCurrentCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 );
|
||
|
||
gWR.SetWeaponConfig(nullptr, 1);
|
||
}
|
||
else
|
||
{
|
||
memset( &m_crosshairRect,0,sizeof(m_crosshairRect) );
|
||
gHUD.SetCurrentCrosshair( 0, m_crosshairRect, 0, 0, 0 );
|
||
|
||
gWR.SetWeaponConfig(nullptr, -1);
|
||
}
|
||
|
||
// Removed by mmcguire.
|
||
/*
|
||
// if we are a real player on server don't allow inset window
|
||
// in First Person mode since this is our resticted forcecamera mode 2
|
||
// team number 3 = SPECTATOR see player.h
|
||
|
||
if ( ( (g_iTeamNumber == 1) || (g_iTeamNumber == 2)) && (g_iUser1 == OBS_IN_EYE) )
|
||
m_pip->value = INSET_OFF;
|
||
*/
|
||
|
||
// draw small border around inset view, adjust upper black bar
|
||
//gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF );
|
||
gViewPort->m_pSpectatorPanel->EnableInsetView( IsInOverviewMode() );
|
||
|
||
}
|
||
|
||
|
||
void CHudSpectator::Reset()
|
||
{
|
||
// Reset HUD
|
||
if ( strcmp( m_OverviewData.map, gEngfuncs.pfnGetLevelName() ) )
|
||
{
|
||
// update level overview if level changed
|
||
ParseOverviewFile();
|
||
LoadMapSprites();
|
||
}
|
||
|
||
memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
|
||
|
||
SetSpectatorStartPosition();
|
||
}
|
||
|
||
void CHudSpectator::InitHUDData()
|
||
{
|
||
gHUD.InitHUDData();
|
||
m_lastPrimaryObject = m_lastSecondaryObject = 0;
|
||
m_flNextObserverInput = 0.0f;
|
||
m_lastHudMessage = 0;
|
||
m_iSpectatorNumber = 0;
|
||
iJumpSpectator = 0;
|
||
g_iUser1 = g_iUser2 = 0;
|
||
|
||
memset( &m_OverviewData, 0, sizeof(m_OverviewData));
|
||
memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities));
|
||
|
||
if ( gEngfuncs.IsSpectateOnly() || gEngfuncs.pDemoAPI->IsPlayingback() )
|
||
m_autoDirector->value = 1.0f;
|
||
else
|
||
m_autoDirector->value = 0.0f;
|
||
|
||
Reset();
|
||
|
||
SetMode( OBS_CHASE_FREE);
|
||
|
||
g_iUser2 = 0; // fake not target until first camera command
|
||
|
||
// reset HUD FOV
|
||
//gHUD.m_iFOV = CVAR_GET_FLOAT("default_fov");
|
||
gHUD.m_iFOV = 90;
|
||
}
|
||
|