You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3994 lines
94 KiB
3994 lines
94 KiB
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
#include "cbase.h"
|
|
#include "hudelement.h"
|
|
#include "sfhudradar.h"
|
|
#include "hudelement.h"
|
|
#include "hud_macros.h"
|
|
#include <filesystem.h>
|
|
#include "cs_gamerules.h"
|
|
#include "c_team.h"
|
|
#include "c_cs_playerresource.h"
|
|
#include "c_plantedc4.h"
|
|
#include "c_cs_hostage.h"
|
|
#include "vtf/vtf.h"
|
|
#include "clientmode.h"
|
|
#include "voice_status.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include <vstdlib/vstrtools.h>
|
|
#include "view.h"
|
|
#include "gameui_util.h"
|
|
#include "sfhudfreezepanel.h"
|
|
#include "sfhudwinpanel.h"
|
|
#include "c_plantedc4.h"
|
|
#include "HUD/sfhud_teamcounter.h"
|
|
#include "gametypes.h"
|
|
#include "eventlist.h"
|
|
#include <game/client/iviewport.h>
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
static const float RADARRADIUS = 58.0f;
|
|
static const float DEAD_FADE_TIME = 4.0f;
|
|
static const float GHOST_FADE_TIME = 6.0f;
|
|
static const float BOMB_FADE_TIME = 8.0f;
|
|
static const float DEFUSER_FADE_TIME = 8.0f;
|
|
static const float TIMER_INIT = -1000.0f;
|
|
static const int ABOVE_BELOW_HEIGHT = 94;
|
|
static const int INVALID_INDEX = -1;
|
|
|
|
extern ConVar cl_draw_only_deathnotices;
|
|
extern ConVar cl_radar_square_with_scoreboard;
|
|
|
|
/*******************************************************************************
|
|
* data definitions
|
|
*/
|
|
|
|
static const char* playerIconNames[] = {
|
|
"PlayerNumber",
|
|
"PlayerLetter",
|
|
"PlayerIndicator",
|
|
"SpeakingOnMap",
|
|
"SpeakingOffMap",
|
|
"AbovePlayer",
|
|
"BelowPlayer",
|
|
"HostageTransitOnMap",
|
|
"HostageTransitOffMap",
|
|
"CTOnMap",
|
|
"CTOffMap",
|
|
"CTDeath",
|
|
"CTGhost",
|
|
"TOnMap",
|
|
"TOffMap",
|
|
"TDeath",
|
|
"TGhost",
|
|
"EnemyOnMap",
|
|
"EnemyOffMap",
|
|
"EnemyDeath",
|
|
"EnemyGhost",
|
|
"HostageOnMap",
|
|
"HostageOffMap",
|
|
"HostageDeath",
|
|
"HostageGhost",
|
|
"DirectionalIndicator",
|
|
"Defuser",
|
|
"Selected",
|
|
"ViewFrustrum",
|
|
"EnemyOnMapSeeOther",
|
|
NULL
|
|
};
|
|
|
|
static const char* hostageIconNames[] = {
|
|
"HostageDead",
|
|
"HostageRescued",
|
|
"HostageAlive",
|
|
"HostageTransit",
|
|
NULL
|
|
};
|
|
|
|
static const char* radarIconNames[] = {
|
|
"BombPlantedIcon",
|
|
"BombPlantedIconMedium",
|
|
"BombPlantedIconFast",
|
|
"HostageZoneIcon",
|
|
NULL
|
|
};
|
|
|
|
static const char *desiredMessageNames[] = {
|
|
"game_newmap",
|
|
"round_start",
|
|
"player_connect",
|
|
"player_info",
|
|
"player_team",
|
|
"player_spawn",
|
|
"player_death",
|
|
"player_disconnect",
|
|
"hostage_killed",
|
|
"hostage_rescued",
|
|
"bomb_defused",
|
|
"bomb_exploded",
|
|
"bomb_planted",
|
|
"bomb_pickup",
|
|
"bomb_dropped",
|
|
"defuser_pickup",
|
|
"defuser_dropped",
|
|
"decoy_started",
|
|
"decoy_detonate",
|
|
"bot_takeover",
|
|
NULL
|
|
};
|
|
|
|
enum DESIRED_MESSAGE_INDICES
|
|
{
|
|
GAME_NEWMAP,
|
|
ROUND_POST_START,
|
|
PLAYER_CONNECT,
|
|
PLAYER_INFO,
|
|
PLAYER_TEAM,
|
|
PLAYER_SPAWN,
|
|
PLAYER_DEATH,
|
|
PLAYER_DISCONNECT,
|
|
HOSTAGE_KILLED,
|
|
HOSTAGE_RESCUED,
|
|
BOMB_DEFUSED,
|
|
BOMB_EXPLODED,
|
|
BOMB_PLANTED,
|
|
BOMB_PICKUP,
|
|
BOMB_DROPPED,
|
|
DEFUSER_PICKUP,
|
|
DEFUSER_DROPPED,
|
|
DECOY_STARTED,
|
|
DECOY_DETONATE,
|
|
BOT_TAKEOVER,
|
|
|
|
};
|
|
|
|
/***************************************************
|
|
* callback and function declarations
|
|
*/
|
|
|
|
static bool maplessfunc( const char* const & s1, const char* const & s2 )
|
|
{
|
|
return V_strcmp( s1, s2 ) < 0;
|
|
}
|
|
|
|
CUtlMap<const char*, int> SFHudRadar::m_messageMap( maplessfunc );
|
|
|
|
DECLARE_HUDELEMENT( SFHudRadar );
|
|
DECLARE_HUD_MESSAGE( SFHudRadar, ProcessSpottedEntityUpdate );
|
|
|
|
SFUI_BEGIN_GAME_API_DEF
|
|
SFUI_DECL_METHOD( MapLoaded ),
|
|
SFUI_END_GAME_API_DEF( SFHudRadar, Radar );
|
|
|
|
CON_COMMAND( drawradar, "Draws HUD radar" )
|
|
{
|
|
( GET_HUDELEMENT( SFHudRadar ) )->ShowRadar( true );
|
|
}
|
|
|
|
CON_COMMAND( hideradar, "Hides HUD radar" )
|
|
{
|
|
( GET_HUDELEMENT( SFHudRadar ) )->ShowRadar( false );
|
|
}
|
|
|
|
CON_COMMAND( cl_reload_hud, "Reloads the hud scale and resets scale and borders" )
|
|
{
|
|
( GET_HUDELEMENT( SFHudRadar ) )->ResizeHud();
|
|
}
|
|
|
|
ConVar cl_radar_rotate( "cl_radar_rotate", "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "1" );
|
|
ConVar cl_radar_scale( "cl_radar_scale", "0.7", FCVAR_RELEASE | FCVAR_ARCHIVE, "Sets the radar scale. Valid values are 0.25 to 1.0.", true, 0.25f, true, 1.0f );
|
|
ConVar cl_radar_always_centered( "cl_radar_always_centered", "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "If set to 0, the radar is maximally used. Otherwise the player is always centered, even at map extents." );
|
|
ConVar cl_radar_icon_scale_min( "cl_radar_icon_scale_min", "0.6", FCVAR_RELEASE | FCVAR_ARCHIVE, "Sets the minimum icon scale. Valid values are 0.4 to 1.0.", true, 0.4f, true, 1.0f );
|
|
ConVar cl_radar_fast_transforms( "cl_radar_fast_transforms", "1", FCVAR_DEVELOPMENTONLY, "Faster way of placing icons on the mini map." );
|
|
|
|
/**********************************************************************
|
|
* SFHudRadarIconPackage code
|
|
*/
|
|
|
|
SFHudRadar::SFHudRadarIconPackage::SFHudRadarIconPackage()
|
|
{
|
|
ClearAll();
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarIconPackage::~SFHudRadarIconPackage()
|
|
{
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::ClearAll( void )
|
|
{
|
|
m_IconPackage = NULL;
|
|
m_IconPackageRotate = NULL;
|
|
|
|
V_memset( m_Icons, 0, sizeof( m_Icons ) );
|
|
|
|
m_pScaleformUI = NULL;
|
|
|
|
m_iCurrentVisibilityFlags = 0;
|
|
m_fCurrentAlpha = 1.0f;
|
|
|
|
m_Health = 0;
|
|
m_iPlayerType = 0;
|
|
m_iIndex = INVALID_INDEX;
|
|
m_iEntityID = 0;
|
|
|
|
m_bIsActive = false;
|
|
m_bOffMap = true;
|
|
|
|
m_bIsSpotted = false;
|
|
m_bIsSpottedByFriendsOnly = false;
|
|
m_fGhostTime = TIMER_INIT;
|
|
|
|
m_fLastColorUpdate = TIMER_INIT;
|
|
|
|
m_bIsDead = false;
|
|
m_fDeadTime = TIMER_INIT;
|
|
|
|
m_fGrenExpireTime = TIMER_INIT;
|
|
|
|
m_IconPackType = ICON_PACK_PLAYER;
|
|
m_bIsRescued = false;
|
|
|
|
m_bIsOnLocalTeam = false;
|
|
|
|
m_fRoundStartTime = TIMER_INIT;
|
|
|
|
m_wcName[0] = 0;
|
|
|
|
m_Position = vec3_origin;
|
|
m_Angle.Init();
|
|
|
|
m_HudPosition = vec3_origin;
|
|
m_HudRotation = 0.0f;
|
|
m_HudScale = 1.0f;
|
|
|
|
m_bIsDefuser = false;
|
|
|
|
m_bHostageIsUsed = false;
|
|
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::Init( IScaleformUI* pui, SFVALUE iconPackage )
|
|
{
|
|
m_pScaleformUI = pui;
|
|
m_IconPackage = pui->CreateValue( iconPackage );
|
|
m_IconPackageRotate = m_pScaleformUI->Value_GetMember( iconPackage, "RotatedLayer" );
|
|
|
|
for ( int i = 0; i < PI_NUM_ICONS && playerIconNames[i] != NULL; i++ )
|
|
{
|
|
if ( i < PI_FIRST_ROTATED )
|
|
{
|
|
m_Icons[i] = pui->Value_GetMember( iconPackage, playerIconNames[i] );
|
|
}
|
|
else
|
|
{
|
|
if ( m_IconPackageRotate )
|
|
{
|
|
m_Icons[i] = pui->Value_GetMember( m_IconPackageRotate, playerIconNames[i] );
|
|
}
|
|
}
|
|
|
|
if ( m_Icons[i] )
|
|
{
|
|
pui->Value_SetVisible( m_Icons[i], ( m_iCurrentVisibilityFlags & ( 1 << i ) ) != 0 );
|
|
}
|
|
}
|
|
|
|
ScaleformDisplayInfo displayInfo;
|
|
displayInfo.SetAlpha( m_fCurrentAlpha * 100.0f );
|
|
displayInfo.SetVisibility( m_iCurrentVisibilityFlags != 0 );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_IconPackage, &displayInfo );
|
|
}
|
|
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::NukeFromOrbit( SFHudRadar* pSFUI )
|
|
{
|
|
if ( pSFUI->FlashAPIIsValid() )
|
|
{
|
|
pSFUI->SafeReleaseSFVALUE( m_IconPackage );
|
|
pSFUI->SafeReleaseSFVALUE( m_IconPackageRotate );
|
|
|
|
for ( int i = 0; i < PI_NUM_ICONS; i++ )
|
|
{
|
|
pSFUI->SafeReleaseSFVALUE( m_Icons[i] );
|
|
}
|
|
}
|
|
|
|
ClearAll();
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::StartRound( void )
|
|
{
|
|
m_Health = 100;
|
|
|
|
m_bOffMap = false;
|
|
m_bIsSpotted = false;
|
|
m_bIsSpottedByFriendsOnly = false;
|
|
m_fGhostTime = TIMER_INIT;
|
|
|
|
m_fLastColorUpdate = TIMER_INIT;
|
|
|
|
m_bIsDead = false;
|
|
m_fDeadTime = TIMER_INIT;
|
|
|
|
m_fGrenExpireTime = TIMER_INIT;
|
|
|
|
m_bIsRescued = false;
|
|
|
|
m_nAboveOrBelow = R_SAMELEVEL;
|
|
|
|
m_fRoundStartTime = gpGlobals->curtime;
|
|
|
|
m_Position = vec3_origin;
|
|
m_Angle.Init();
|
|
|
|
SetAlpha( 0 );
|
|
SetVisibilityFlags( 0 );
|
|
}
|
|
|
|
bool SFHudRadar::SFHudRadarIconPackage::IsVisible( void )
|
|
{
|
|
return ( m_fCurrentAlpha != 0 && m_iCurrentVisibilityFlags != 0 );
|
|
}
|
|
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsPlayer( bool value )
|
|
{
|
|
m_bIsPlayer = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsSelected( bool value )
|
|
{
|
|
m_bIsSelected = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsSpeaking ( bool value )
|
|
{
|
|
m_bIsSpeaking = value && m_bIsOnLocalTeam;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsOffMap( bool value )
|
|
{
|
|
m_bOffMap = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsAboveOrBelow( int value )
|
|
{
|
|
m_nAboveOrBelow = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsMovingHostage( bool value )
|
|
{
|
|
m_bIsMovingHostage = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsRescued( bool value )
|
|
{
|
|
m_bIsRescued = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsOnLocalTeam( bool value )
|
|
{
|
|
m_bIsOnLocalTeam = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsBot( bool value )
|
|
{
|
|
m_bIsBot = value;
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsControlledBot( void )
|
|
{
|
|
m_bIsDead = true;
|
|
//m_bIsSpotted = false;
|
|
m_bIsSpotted = true;
|
|
m_fDeadTime = TIMER_INIT;
|
|
m_fGhostTime = TIMER_INIT;
|
|
m_fLastColorUpdate = TIMER_INIT;
|
|
}
|
|
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsDead( bool value )
|
|
{
|
|
if ( value != m_bIsDead )
|
|
{
|
|
if ( value )
|
|
{
|
|
// SetIsSpotted( true );
|
|
m_fDeadTime = gpGlobals->curtime;
|
|
}
|
|
else
|
|
{
|
|
m_fDeadTime = TIMER_INIT;
|
|
}
|
|
|
|
m_bIsDead = value;
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetGrenadeExpireTime( float value )
|
|
{
|
|
if ( value )
|
|
{
|
|
m_fGrenExpireTime = value;
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsSpotted( bool value )
|
|
{
|
|
if ( gpGlobals->curtime - m_fRoundStartTime > 0.25f )
|
|
{
|
|
if ( value != m_bIsSpotted )
|
|
{
|
|
if ( !value )
|
|
{
|
|
m_fGhostTime = gpGlobals->curtime;
|
|
}
|
|
else
|
|
{
|
|
m_fGhostTime = TIMER_INIT;
|
|
}
|
|
|
|
m_bIsSpotted = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsSpottedByFriendsOnly( bool value )
|
|
{
|
|
if ( gpGlobals->curtime - m_fRoundStartTime > 0.25f )
|
|
{
|
|
m_bIsSpottedByFriendsOnly = value;
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetPlayerTeam( int team )
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if( pLocalPlayer == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int newType;
|
|
bool bSpec = ((pLocalPlayer && pLocalPlayer->IsSpectator() ) || engine->IsHLTV());
|
|
|
|
switch( team )
|
|
{
|
|
case TEAM_UNASSIGNED:
|
|
newType = PI_HOSTAGE;
|
|
break;
|
|
|
|
case TEAM_TERRORIST:
|
|
newType = pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || bSpec ? PI_T : PI_ENEMY;
|
|
break;
|
|
|
|
case TEAM_CT:
|
|
newType = pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT || bSpec ? PI_CT : PI_ENEMY;
|
|
break;
|
|
|
|
case TEAM_SPECTATOR:
|
|
default:
|
|
newType = 0;
|
|
break;
|
|
}
|
|
|
|
if ( m_iPlayerType != newType )
|
|
{
|
|
m_iPlayerType = newType;
|
|
SetVisibilityFlags( 0 );
|
|
}
|
|
|
|
}
|
|
|
|
bool Helper_ShouldShowAssassinationTargetIcon( int iEntIndex )
|
|
{
|
|
C_CSPlayer *pTarget= (C_CSPlayer*)UTIL_PlayerByIndex( iEntIndex );
|
|
C_CS_PlayerResource *pCSPR = GetCSResources();
|
|
if ( !pTarget || !pCSPR )
|
|
return false;
|
|
|
|
return ( !pCSPR->IsControllingBot( iEntIndex ) &&
|
|
pTarget->IsAssassinationTarget() );
|
|
}
|
|
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetupIconsFromStates( void )
|
|
{
|
|
int flags = 0;
|
|
float alpha = 1;
|
|
|
|
if ( m_iPlayerType != 0 )
|
|
{
|
|
flags = 1 << m_iPlayerType;
|
|
|
|
if ( m_bIsPlayer )
|
|
{
|
|
flags |= 1 << PI_VIEWFRUSTRUM;
|
|
}
|
|
|
|
if ( m_bIsDead )
|
|
{
|
|
if ( m_Position.x == 0 && m_Position.y == 0 || !m_bIsSpotted )
|
|
{
|
|
flags = 0;
|
|
}
|
|
else
|
|
{
|
|
float deadElapsedTime = gpGlobals->curtime - m_fDeadTime;
|
|
if ( deadElapsedTime > DEAD_FADE_TIME )
|
|
{
|
|
m_fDeadTime = TIMER_INIT;
|
|
flags = 0;
|
|
}
|
|
else
|
|
{
|
|
alpha = clamp( 1.0f - deadElapsedTime / DEAD_FADE_TIME, 0.0f, 1.0f );
|
|
|
|
// the shift below changes the icon to be the dead icon ( the X )
|
|
// rescued hostages are marked as dead, but we don't want to show
|
|
// the X in that case. So if this guy is a hostage and has been resuced
|
|
// we want to skip the code that changes the icon to the dead icon.
|
|
|
|
bool isRescuedNotDead = IsHostageType() && m_bIsRescued;
|
|
|
|
if ( !isRescuedNotDead )
|
|
{
|
|
flags <<= 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( !m_bIsSpotted )
|
|
{
|
|
float ghostElapsedTime = gpGlobals->curtime - m_fGhostTime;
|
|
if ( ghostElapsedTime > GHOST_FADE_TIME )
|
|
{
|
|
m_fGhostTime = TIMER_INIT;
|
|
flags = 0;
|
|
}
|
|
else
|
|
{
|
|
alpha = clamp( 1.0f - ghostElapsedTime / GHOST_FADE_TIME, 0.0f, 1.0f );
|
|
|
|
if ( m_bOffMap )
|
|
{
|
|
flags <<= 1;
|
|
}
|
|
else
|
|
{
|
|
flags <<= 3;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
bool bSpec = ( ( pLocalPlayer && pLocalPlayer->IsSpectator() ) || engine->IsHLTV());
|
|
|
|
bool bShowLetters = ( !bSpec && m_iPlayerType != PI_ENEMY && !m_bOffMap && !IsHostageType( ) );
|
|
if ( bSpec )
|
|
{
|
|
flags |= 1 << PI_PLAYER_NUMBER;
|
|
}
|
|
|
|
// this decides if the letter should be shown
|
|
if ( bShowLetters || Helper_ShouldShowAssassinationTargetIcon( m_iEntityID ) )
|
|
{
|
|
flags |= 1 << PI_PLAYER_LETTER;
|
|
}
|
|
|
|
if ( m_bIsMovingHostage )
|
|
{
|
|
flags |= 1 << PI_HOSTAGE_MOVING;
|
|
}
|
|
|
|
if ( m_bIsSpeaking )
|
|
{
|
|
flags |= 1 << PI_SPEAKING;
|
|
}
|
|
|
|
if ( m_bIsSelected )
|
|
{
|
|
flags |= 1 << PI_SELECTED;
|
|
}
|
|
|
|
if ( bSpec == false && m_iPlayerType == PI_ENEMY && (m_bIsSpottedByFriendsOnly == false || pLocalPlayer->IsAlive() == false) )
|
|
{
|
|
flags |= 1 << PI_ENEMY_SEELOCAL;
|
|
}
|
|
|
|
// this will shift the MOVING and SPEAKING icons to their
|
|
// offscreen versions as well ( look at the enum decaration )
|
|
if ( m_bOffMap )
|
|
{
|
|
flags <<= 1;
|
|
}
|
|
else
|
|
{
|
|
if ( m_nAboveOrBelow == R_ABOVE )
|
|
{
|
|
flags |= 1 << PI_ABOVE;
|
|
}
|
|
else if ( m_nAboveOrBelow == R_BELOW )
|
|
{
|
|
flags |= 1 << PI_BELOW;
|
|
}
|
|
else
|
|
{
|
|
if ( !bSpec && /*!bShowNumbers &&*/ m_iPlayerType != PI_ENEMY && !IsHostageType( ) )
|
|
flags |= 1 << PI_DIRECTION_INDICATOR;
|
|
}
|
|
}
|
|
|
|
// if ( m_bIsPlayer )
|
|
// {
|
|
// flags |= 1 << PI_PLAYER_INDICATOR;
|
|
// }
|
|
}
|
|
|
|
if ( m_fGrenExpireTime != TIMER_INIT )
|
|
{
|
|
if ( m_fGrenExpireTime < gpGlobals->curtime )
|
|
{
|
|
m_fGrenExpireTime = TIMER_INIT;
|
|
m_bIsSpotted = false;
|
|
}
|
|
}
|
|
}
|
|
else if ( m_bIsDefuser )
|
|
{
|
|
// only render after we have received a position update
|
|
if ( m_Position != vec3_origin )
|
|
{
|
|
flags |= 1 << PI_DEFUSER;
|
|
|
|
if ( m_bIsSpotted )
|
|
{
|
|
m_fGhostTime = TIMER_INIT;
|
|
alpha = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
float ghostElapsedTime = gpGlobals->curtime - m_fGhostTime;
|
|
if ( ghostElapsedTime > GHOST_FADE_TIME )
|
|
{
|
|
m_fGhostTime = TIMER_INIT;
|
|
flags = 0;
|
|
}
|
|
else
|
|
{
|
|
alpha = clamp( 1.0f - ghostElapsedTime / GHOST_FADE_TIME, 0.0f, 1.0f );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SetAlpha( alpha );
|
|
SetVisibilityFlags( flags );
|
|
UpdateIconsPostion();
|
|
}
|
|
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetVisibilityFlags( int newFlags )
|
|
{
|
|
newFlags &= ( ( 1 << PI_NUM_ICONS )-1 );
|
|
|
|
int diffFlags = m_iCurrentVisibilityFlags ^ newFlags;
|
|
|
|
if ( diffFlags )
|
|
{
|
|
if ( m_IconPackage )
|
|
{
|
|
bool wantVisible = ( newFlags != 0 );
|
|
if ( ( m_iCurrentVisibilityFlags != 0 ) != wantVisible )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_IconPackage, wantVisible );
|
|
}
|
|
|
|
for ( int i = 0; i < PI_NUM_ICONS && ( diffFlags != 0 ); i++, diffFlags >>= 1 )
|
|
{
|
|
if ( (diffFlags & 1) && ( m_Icons[i] ) )
|
|
{
|
|
Assert( m_Icons[i] );
|
|
if ( m_Icons[i] )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_Icons[i], ( newFlags & ( 1 << i ) ) != 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_iCurrentVisibilityFlags = newFlags;
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::UpdateIconsPostion( void )
|
|
{
|
|
int visibilityFlags = m_iCurrentVisibilityFlags;
|
|
|
|
if ( m_IconPackage )
|
|
{
|
|
for ( int i = 0; i < PI_NUM_ICONS && ( visibilityFlags != 0 ); i++, visibilityFlags >>= 1 )
|
|
{
|
|
if ( (visibilityFlags & 1) && ( m_Icons[i] ) )
|
|
{
|
|
Assert( m_Icons[i] );
|
|
ScaleformDisplayInfo displayInfo;
|
|
if ( cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
displayInfo.SetX( m_HudPosition.x );
|
|
displayInfo.SetY( m_HudPosition.y );
|
|
displayInfo.SetXScale( m_HudScale );
|
|
displayInfo.SetYScale( m_HudScale );
|
|
if ( i >= PI_FIRST_ROTATED )
|
|
{
|
|
displayInfo.SetRotation( m_HudRotation );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
displayInfo.SetX( 0.0f );
|
|
displayInfo.SetY( 0.0f );
|
|
displayInfo.SetXScale( 100.0f );
|
|
displayInfo.SetYScale( 100.0f );
|
|
displayInfo.SetRotation( 0.0f );
|
|
}
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_Icons[i], &displayInfo );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetAlpha( float newAlpha )
|
|
{
|
|
if ( newAlpha != m_fCurrentAlpha )
|
|
{
|
|
m_fCurrentAlpha = newAlpha;
|
|
|
|
if ( m_IconPackage )
|
|
{
|
|
ScaleformDisplayInfo displayInfo;
|
|
displayInfo.SetAlpha( m_fCurrentAlpha * 100.0f );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_IconPackage, &displayInfo );
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarIconPackage::SetIsDefuse( bool bValue )
|
|
{
|
|
m_bIsDefuser = bValue;
|
|
}
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
**********************************************************************
|
|
**********************************************************************
|
|
**********************************************************************
|
|
* SFHudHostageIcon
|
|
*/
|
|
|
|
SFHudRadar::SFHudRadarHostageIcons::SFHudRadarHostageIcons()
|
|
{
|
|
m_IconPackage = NULL;
|
|
V_memset( m_Icons, 0,sizeof( m_Icons ) );
|
|
m_iCurrentIcon = HI_UNUSED;
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarHostageIcons::~SFHudRadarHostageIcons()
|
|
{
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarHostageIcons::Init( IScaleformUI* scaleformui, SFVALUE iconPackage )
|
|
{
|
|
m_pScaleformUI = scaleformui;
|
|
m_IconPackage = scaleformui->CreateValue( iconPackage );
|
|
|
|
for ( int i = 0; i < HI_NUM_ICONS && hostageIconNames[i] != NULL; i++ )
|
|
{
|
|
m_Icons[i] = m_pScaleformUI->Value_GetMember( m_IconPackage, hostageIconNames[i] );
|
|
if ( m_Icons[i] )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_Icons[i], m_iCurrentIcon == i );
|
|
}
|
|
}
|
|
|
|
m_pScaleformUI->Value_SetVisible( m_IconPackage, m_iCurrentIcon != HI_UNUSED );
|
|
}
|
|
|
|
void SFHudRadar::SFHudRadarHostageIcons::SetStatus( int status )
|
|
{
|
|
if ( status != m_iCurrentIcon )
|
|
{
|
|
if ( m_IconPackage )
|
|
{
|
|
if ( m_iCurrentIcon != HI_UNUSED )
|
|
{
|
|
assert(m_Icons[m_iCurrentIcon]);
|
|
m_pScaleformUI->Value_SetVisible( m_Icons[m_iCurrentIcon], false );
|
|
}
|
|
else
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_IconPackage, true );
|
|
}
|
|
|
|
m_iCurrentIcon = status;
|
|
|
|
if ( m_iCurrentIcon != HI_UNUSED )
|
|
{
|
|
assert(m_Icons[m_iCurrentIcon]);
|
|
m_pScaleformUI->Value_SetVisible( m_Icons[m_iCurrentIcon], true );
|
|
}
|
|
else
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_IconPackage, false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SFHudRadar::SFHudRadarHostageIcons::ReleaseHandles( SFHudRadar* pradar )
|
|
{
|
|
if ( m_IconPackage && pradar->FlashAPIIsValid() )
|
|
{
|
|
pradar->SafeReleaseSFVALUE( m_IconPackage );
|
|
|
|
for ( int i = 0; i < HI_NUM_ICONS; i++ )
|
|
{
|
|
pradar->SafeReleaseSFVALUE( m_Icons[i] );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
**********************************************************************
|
|
**********************************************************************
|
|
**********************************************************************
|
|
* SFHudRadar Code
|
|
*
|
|
*/
|
|
|
|
SFHudRadar::SFHudRadar( const char *value ) : SFHudFlashInterface( value ),
|
|
m_bVisible( false ),
|
|
m_fMapSize( 1.0f ),
|
|
m_fRadarSize( 1.0f ),
|
|
m_fPixelToRadarScale( 1.0f ),
|
|
m_fWorldToPixelScale( 1.0f ),
|
|
m_fWorldToRadarScale( 1.0f ),
|
|
m_RadarModule( NULL ),
|
|
m_Radar( NULL ),
|
|
m_IconTranslation( NULL ),
|
|
m_IconRotation( NULL ),
|
|
m_MapRotation( NULL ),
|
|
m_MapTranslation( NULL ),
|
|
m_iNumGoalIcons( 0 ),
|
|
m_iLastPlayerIndex( INVALID_INDEX ),
|
|
m_iLastHostageIndex( INVALID_INDEX ),
|
|
m_iLastDecoyIndex( INVALID_INDEX ),
|
|
m_iLastDefuserIndex( INVALID_INDEX ),
|
|
m_RadarViewpointWorld( vec3_origin ),
|
|
m_RadarViewpointMap( vec3_origin ),
|
|
m_RadarRotation( 0 ),
|
|
m_BombPosition( vec3_origin ),
|
|
m_DefuserPosition( vec3_origin ),
|
|
m_iCurrentVisibilityFlags( 0 ),
|
|
m_fBombSeenTime( TIMER_INIT ),
|
|
m_fBombAlpha( 0 ),
|
|
m_fDefuserSeenTime( TIMER_INIT ),
|
|
m_fDefuserAlpha( 0.0f ),
|
|
m_LocationText( NULL ),
|
|
m_bFlashLoading( false ),
|
|
m_bFlashReady( false ),
|
|
m_bGotPlayerIcons( false ),
|
|
m_bShowingHostageZone( false ),
|
|
m_bBombPlanted( false ),
|
|
m_bBombDropped( false ),
|
|
m_nBombEntIndex( -1 ),
|
|
m_nBombHolderUserId( -1 ),
|
|
m_bShowBombHighlight( false ),
|
|
m_bShowRadar( true ),
|
|
m_bShowAll( false ),
|
|
m_bShowingDashboard( false ),
|
|
m_iObserverMode( OBS_MODE_NONE ),
|
|
m_bTrackDefusers( false ),
|
|
m_bRound( true )
|
|
{
|
|
SetHiddenBits( HIDEHUD_RADAR );
|
|
m_bWantLateUpdate = true;
|
|
|
|
m_cDesiredMapName[0] = 0;
|
|
m_cLoadedMapName[0] = 0;
|
|
m_wcLocationString[0] = 0;
|
|
|
|
V_memset( m_BombZoneIcons, 0, sizeof( m_BombZoneIcons ) );
|
|
V_memset( m_HostageZoneIcons, 0, sizeof( m_HostageZoneIcons ) );
|
|
V_memset( m_GoalIcons, 0, sizeof( m_GoalIcons ) );
|
|
V_memset( m_HostageStatusIcons, 0, sizeof( m_HostageStatusIcons ) );
|
|
V_memset( m_Icons, 0, sizeof( m_Icons ) );
|
|
|
|
m_EntitySpotted.ClearAll();
|
|
|
|
m_nCurrentRadarVerticalSection = -1;
|
|
m_vecRadarVerticalSections.RemoveAll();
|
|
}
|
|
|
|
|
|
SFHudRadar::~SFHudRadar()
|
|
{
|
|
}
|
|
|
|
/**************************************
|
|
* hud element functions
|
|
*/
|
|
|
|
void SFHudRadar::Init( void )
|
|
{
|
|
// register for events as client listener
|
|
|
|
const char** pwalk = &desiredMessageNames[0];
|
|
|
|
while( *pwalk != NULL )
|
|
{
|
|
ListenForGameEvent( *pwalk );
|
|
pwalk++;
|
|
}
|
|
|
|
if ( ! m_messageMap.Count() )
|
|
{
|
|
const char** pwalk = &desiredMessageNames[0];
|
|
int i = 0;
|
|
|
|
while( *pwalk != NULL )
|
|
{
|
|
m_messageMap.Insert( *pwalk++, i++ );
|
|
}
|
|
}
|
|
|
|
HOOK_HUD_MESSAGE( SFHudRadar, ProcessSpottedEntityUpdate );
|
|
}
|
|
|
|
void SFHudRadar::LevelInit( void )
|
|
{
|
|
if ( !m_bFlashReady && !m_bFlashLoading )
|
|
{
|
|
SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudRadar, this, Radar );
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudRadar::LevelShutdown( void )
|
|
{
|
|
if ( m_bFlashReady || m_bFlashLoading )
|
|
{
|
|
RemoveFlashElement();
|
|
}
|
|
}
|
|
|
|
ConVar cl_drawhud_force_radar( "cl_drawhud_force_radar", "0", FCVAR_RELEASE, "0: default; 1: draw radar even if hud disabled; -1: force no radar" );
|
|
bool SFHudRadar::ShouldDraw( void )
|
|
{
|
|
if ( IsTakingAFreezecamScreenshot() )
|
|
return false;
|
|
|
|
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer( );
|
|
if ( !pPlayer )
|
|
return false;
|
|
|
|
bool bSpec = pPlayer->IsSpectator( ) || engine->IsHLTV( );
|
|
|
|
if ( bSpec == false )
|
|
{
|
|
// //Don't show the radar while the win panel is up (only look at slot 0 because that is the only "true" Win Panel)
|
|
// SFHudWinPanel * pWinPanel = ( SFHudWinPanel* ) ( GetHud( 0 ).FindElement( "SFHudWinPanel" ) );
|
|
// if ( pWinPanel && pWinPanel->IsVisible( ) )
|
|
// {
|
|
// return false;
|
|
// }
|
|
|
|
if ( pPlayer->GetTeamNumber() == TEAM_UNASSIGNED ||
|
|
( pPlayer->GetTeamNumber() == TEAM_UNASSIGNED && pPlayer->GetPendingTeamNumber() != TEAM_SPECTATOR ) )
|
|
return false;
|
|
}
|
|
|
|
return m_bShowRadar && ( cl_drawhud_force_radar.GetInt() >= 0 ) && (
|
|
( cl_drawhud_force_radar.GetInt() > 0 ) ||
|
|
( cl_drawhud.GetBool() && cl_draw_only_deathnotices.GetBool() == false )
|
|
) && CHudElement::ShouldDraw();
|
|
}
|
|
|
|
|
|
void SFHudRadar::SetActive( bool bActive )
|
|
{
|
|
if ( bActive != m_bVisible )
|
|
Show( bActive );
|
|
|
|
CHudElement::SetActive( bActive );
|
|
}
|
|
|
|
void SFHudRadar::Show( bool show )
|
|
{
|
|
if ( !m_pScaleformUI )
|
|
return;
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
if ( show )
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showPanel", NULL, 0 );
|
|
|
|
for ( int i = 0; i <= MAX_PLAYERS; ++i )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( i );
|
|
if ( pPackage )
|
|
pPackage->m_fLastColorUpdate = TIMER_INIT;
|
|
}
|
|
|
|
UpdateAllPlayerNumbers();
|
|
|
|
m_bVisible = true;
|
|
}
|
|
else
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hidePanel", NULL, 0 );
|
|
m_bVisible = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**********************************
|
|
* initialization code goes here
|
|
*/
|
|
|
|
|
|
// these overload the ScaleformFlashInterfaceMixin class
|
|
void SFHudRadar::FlashLoaded( void )
|
|
{
|
|
m_RadarModule = m_pScaleformUI->Value_GetMember( m_FlashAPI, "RadarModule" );
|
|
|
|
if ( !m_RadarModule )
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_Radar = m_pScaleformUI->Value_GetMember( m_RadarModule, "Radar" );
|
|
|
|
if ( m_Radar )
|
|
{
|
|
|
|
m_MapRotation = m_pScaleformUI->Value_GetMember( m_Radar, "MapRotation" );
|
|
|
|
if ( m_MapRotation )
|
|
{
|
|
m_MapTranslation =m_pScaleformUI->Value_GetMember( m_MapRotation, "MapTranslation" );
|
|
}
|
|
|
|
|
|
m_IconRotation = m_pScaleformUI->Value_GetMember( m_Radar, "IconRotation" );
|
|
|
|
if ( !m_IconRotation )
|
|
return;
|
|
|
|
m_IconTranslation = m_pScaleformUI->Value_GetMember( m_IconRotation, "IconTranslation" );
|
|
|
|
if ( !m_IconTranslation )
|
|
return;
|
|
|
|
char cHostageZoneIconName[20] = {"HZone0"};
|
|
|
|
for ( int i = 0; i < MAX_HOSTAGE_RESCUES; i++ )
|
|
{
|
|
cHostageZoneIconName[5] = '0'+i;
|
|
m_HostageZoneIcons[i] = m_pScaleformUI->Value_GetMember( m_IconTranslation, cHostageZoneIconName );
|
|
}
|
|
|
|
m_BombZoneIcons[0] = m_pScaleformUI->Value_GetMember( m_IconTranslation, "BombZoneA" );
|
|
m_BombZoneIcons[1] = m_pScaleformUI->Value_GetMember( m_IconTranslation, "BombZoneB" );
|
|
|
|
}
|
|
|
|
SFVALUE dashboard = m_pScaleformUI->Value_GetMember( m_RadarModule, "Dashboard" );
|
|
m_Icons[RI_DASHBOARD] = dashboard;
|
|
|
|
if ( !dashboard )
|
|
return;
|
|
|
|
//SFVALUE C4andHostages = m_pScaleformUI->Value_GetMember( m_RadarModule, "C4" );
|
|
//if ( !C4andHostages )
|
|
// return;
|
|
|
|
SFVALUE hostageIcons = m_pScaleformUI->Value_GetMember( m_RadarModule, "Hostages" );
|
|
|
|
char hostageIconName[20] = {"HostageStatusX"};
|
|
|
|
int index = 0;
|
|
SFVALUE hostageIcon;
|
|
|
|
do
|
|
{
|
|
hostageIconName[13] = index + '1';
|
|
hostageIcon = m_pScaleformUI->Value_GetMember( hostageIcons, hostageIconName );
|
|
if ( hostageIcon == NULL )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
m_HostageStatusIcons[index].Init( m_pScaleformUI, hostageIcon );
|
|
SafeReleaseSFVALUE( hostageIcon );
|
|
}
|
|
|
|
} while( ++index < MAX_HOSTAGES );
|
|
|
|
for ( int i = 0; radarIconNames[i] != NULL; i++ )
|
|
{
|
|
m_Icons[i] = m_pScaleformUI->Value_GetMember( hostageIcons, radarIconNames[i] );
|
|
}
|
|
|
|
m_LocationText = m_pScaleformUI->TextObject_MakeTextObjectFromMember( dashboard, "Location" );
|
|
if ( m_LocationText )
|
|
{
|
|
m_LocationText->SetText( m_wcLocationString );
|
|
}
|
|
|
|
SafeReleaseSFVALUE( hostageIcons );
|
|
}
|
|
|
|
|
|
void SFHudRadar::FlashReady( void )
|
|
{
|
|
// these aren't ready until after the first frame, so they have to get connected here instead of in
|
|
// FlashLoaded()
|
|
|
|
m_Icons[RI_BOMB_ICON_PACKAGE] = m_pScaleformUI->Value_Invoke( m_IconTranslation, "createBombPack", NULL, 0 );
|
|
if ( m_Icons[RI_BOMB_ICON_PACKAGE] )
|
|
{
|
|
m_Icons[RI_BOMB_ICON_DROPPED] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "DroppedBomb" );
|
|
m_Icons[RI_BOMB_ICON_PLANTED] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "PlantedBomb" );
|
|
m_Icons[RI_BOMB_ICON_BOMB_CT] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombCT" );
|
|
m_Icons[RI_BOMB_ICON_BOMB_T] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombT" );
|
|
|
|
m_Icons[RI_BOMB_ICON_BOMB_ABOVE] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombAbove" );
|
|
m_Icons[RI_BOMB_ICON_BOMB_BELOW] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombBelow" );
|
|
}
|
|
|
|
for ( int i = 0; i < RI_NUM_ICONS; i++ )
|
|
{
|
|
if ( m_Icons[i] )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_Icons[i], false );
|
|
}
|
|
}
|
|
|
|
m_bFlashLoading = false;
|
|
m_bFlashReady = true;
|
|
ResetForNewMap();
|
|
|
|
// there will be a map waiting for us to load
|
|
|
|
FlashLoadMap( NULL );
|
|
//
|
|
// if ( m_bActive )
|
|
// {
|
|
// m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showPanel", NULL, 0 );
|
|
// m_bVisible = true;
|
|
// }
|
|
// else
|
|
// {
|
|
// m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hidePanel", NULL, 0 );
|
|
// m_bVisible = false;
|
|
// }
|
|
}
|
|
|
|
void SFHudRadar::LazyCreateGoalIcons( void )
|
|
{
|
|
if ( m_bGotGoalIcons || !m_bFlashReady )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// The goal entities don't exist on the client, so we have to get them from the CS Resource.
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
if ( !pCSPR )
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_iNumGoalIcons = 0;
|
|
|
|
if ( CSGameRules()->IsBombDefuseMap() )
|
|
{
|
|
|
|
Vector bombA = pCSPR->GetBombsiteAPosition();
|
|
if( bombA != vec3_origin )
|
|
{
|
|
m_GoalIcons[m_iNumGoalIcons].m_Position = bombA;
|
|
m_GoalIcons[m_iNumGoalIcons].m_Icon = m_BombZoneIcons[0];
|
|
m_pScaleformUI->Value_SetVisible( m_GoalIcons[m_iNumGoalIcons].m_Icon, true );
|
|
m_iNumGoalIcons++;
|
|
}
|
|
|
|
Vector bombB = pCSPR->GetBombsiteBPosition();
|
|
if( bombB != vec3_origin )
|
|
{
|
|
m_GoalIcons[m_iNumGoalIcons].m_Position = bombB;
|
|
m_GoalIcons[m_iNumGoalIcons].m_Icon = m_BombZoneIcons[1];
|
|
m_pScaleformUI->Value_SetVisible( m_GoalIcons[m_iNumGoalIcons].m_Icon, true );
|
|
m_iNumGoalIcons++;
|
|
}
|
|
}
|
|
else if ( CSGameRules()->IsHostageRescueMap() )
|
|
{
|
|
for( int rescueIndex = 0; rescueIndex < MAX_HOSTAGE_RESCUES; rescueIndex++ )
|
|
{
|
|
int hIndex = 0;
|
|
Vector hostageI = pCSPR->GetHostageRescuePosition( rescueIndex );
|
|
if( hostageI != vec3_origin )
|
|
{
|
|
m_GoalIcons[m_iNumGoalIcons].m_Position = hostageI;
|
|
m_GoalIcons[m_iNumGoalIcons].m_Icon = m_HostageZoneIcons[hIndex++];
|
|
m_pScaleformUI->Value_SetVisible( m_GoalIcons[m_iNumGoalIcons].m_Icon, true );
|
|
m_iNumGoalIcons++;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_bGotGoalIcons = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SFHudRadar::PreUnloadFlash( void )
|
|
{
|
|
if ( m_IconTranslation )
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IconTranslation, "removeBombPack", NULL, 0 );
|
|
}
|
|
|
|
for ( int i = 0; i < MAX_BOMB_ZONES; i++ )
|
|
{
|
|
SafeReleaseSFVALUE( m_BombZoneIcons[i] );
|
|
}
|
|
|
|
for ( int i = 0; i < MAX_HOSTAGE_RESCUES; i++ )
|
|
{
|
|
SafeReleaseSFVALUE( m_HostageZoneIcons[i] );
|
|
}
|
|
|
|
while( m_iLastPlayerIndex >= 0 )
|
|
{
|
|
RemovePlayer( m_iLastPlayerIndex );
|
|
}
|
|
|
|
while( m_iLastHostageIndex >= 0 )
|
|
{
|
|
RemoveHostage( m_iLastHostageIndex );
|
|
}
|
|
|
|
RemoveAllDefusers();
|
|
|
|
RemoveAllDecoys();
|
|
|
|
SafeReleaseSFVALUE( m_MapRotation );
|
|
SafeReleaseSFVALUE( m_MapTranslation );
|
|
|
|
SafeReleaseSFVALUE( m_RadarModule );
|
|
SafeReleaseSFVALUE( m_Radar );
|
|
SafeReleaseSFVALUE( m_IconTranslation );
|
|
SafeReleaseSFVALUE( m_IconRotation );
|
|
|
|
|
|
|
|
|
|
SafeReleaseSFTextObject( m_LocationText );
|
|
|
|
int index = 0;
|
|
while( m_HostageStatusIcons[index].m_IconPackage )
|
|
{
|
|
m_HostageStatusIcons[index++].ReleaseHandles( this );
|
|
}
|
|
|
|
for ( int i =0 ; i < RI_NUM_ICONS; i++ )
|
|
{
|
|
SafeReleaseSFVALUE( m_Icons[i] );
|
|
}
|
|
|
|
m_bFlashReady = false;
|
|
m_cDesiredMapName[0] = 0;
|
|
m_cLoadedMapName[0] = 0;
|
|
|
|
m_bActive = false;
|
|
m_bVisible = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*********************************************************
|
|
* set up the background map
|
|
*/
|
|
|
|
void SFHudRadar::SetMap( const char* pMapName )
|
|
{
|
|
FlashLoadMap( pMapName );
|
|
|
|
KeyValues* MapKeyValues = new KeyValues( pMapName );
|
|
|
|
char tempfile[MAX_PATH];
|
|
Q_snprintf( tempfile, sizeof( tempfile ), "resource/overviews/%s.txt", pMapName );
|
|
|
|
if ( !MapKeyValues->LoadFromFile( g_pFullFileSystem, tempfile, "GAME" ) )
|
|
{
|
|
DevMsg( 1, "Error! CMapOverview::SetMap: couldn't load file %s.\n", tempfile );
|
|
m_MapOrigin.x = 0;
|
|
m_MapOrigin.y = 0;
|
|
return;
|
|
}
|
|
|
|
KeyValues* pSections = MapKeyValues->FindKey( "verticalsections" );
|
|
if ( pSections )
|
|
{
|
|
int nIndex = 0;
|
|
for ( KeyValues *kSection = pSections->GetFirstSubKey(); kSection != NULL; kSection = kSection->GetNextKey() )
|
|
{
|
|
float flAltMin = kSection->GetFloat( "AltitudeMin", 0.0f );
|
|
float flAltMax = kSection->GetFloat( "AltitudeMax", 0.0f );
|
|
|
|
if ( flAltMin < flAltMax )
|
|
{
|
|
HudRadarLevelVerticalSection_t *pNewSection = &m_vecRadarVerticalSections[ m_vecRadarVerticalSections.AddToTail() ];
|
|
|
|
if ( !V_strcmp( kSection->GetName(), "default" ) )
|
|
{
|
|
V_strcpy_safe( pNewSection->m_szSectionName, pMapName );
|
|
}
|
|
else
|
|
{
|
|
V_sprintf_safe( pNewSection->m_szSectionName, "%s_%s", pMapName, kSection->GetName() );
|
|
}
|
|
|
|
pNewSection->m_nSectionIndex = nIndex;
|
|
pNewSection->m_flSectionAltitudeFloor = flAltMin;
|
|
pNewSection->m_flSectionAltitudeCeiling = flAltMax;
|
|
nIndex++;
|
|
}
|
|
else
|
|
{
|
|
DevWarning( "Radar vertical section is invalid!\n" );
|
|
}
|
|
}
|
|
|
|
if ( m_vecRadarVerticalSections.Count() )
|
|
{
|
|
DevMsg( "Loaded radar vertical section keyvalues.\n" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// map doesn't have sections, clear any sections from previous map
|
|
// TODO: Perhaps initialize a single giant vertical section that covers the whole map,
|
|
// to reduce variation in handling radar in downstream code?
|
|
m_vecRadarVerticalSections.Purge();
|
|
}
|
|
|
|
// TODO release old texture ?
|
|
|
|
m_MapOrigin.x = MapKeyValues->GetInt( "pos_x" );
|
|
m_MapOrigin.y = MapKeyValues->GetInt( "pos_y" );
|
|
m_MapOrigin.z = 0;
|
|
m_fWorldToPixelScale = 1.0f / MapKeyValues->GetFloat( "scale", 1.0f );
|
|
|
|
m_fWorldToRadarScale = m_fWorldToPixelScale * m_fPixelToRadarScale;
|
|
|
|
MapKeyValues->deleteThis();
|
|
|
|
}
|
|
|
|
|
|
void SFHudRadar::FlashLoadMap( const char* pMapName )
|
|
{
|
|
const char* pMapToLoad = pMapName ? pMapName : m_cDesiredMapName;
|
|
|
|
if ( V_strcmp( pMapToLoad, m_cLoadedMapName ) )
|
|
{
|
|
V_strcpy_safe( m_cDesiredMapName, pMapToLoad );
|
|
|
|
if ( m_bFlashReady )
|
|
{
|
|
if (!m_vecRadarVerticalSections.Count())
|
|
{
|
|
// Single map
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 1)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, pMapToLoad);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "loadMap", args, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Multiple map levels
|
|
int numArgs = m_vecRadarVerticalSections.Count() + 1;
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, numArgs)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, pMapToLoad);
|
|
FOR_EACH_VEC(m_vecRadarVerticalSections, i)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, i + 1, m_vecRadarVerticalSections[i].m_szSectionName);
|
|
}
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "loadMap2", args, numArgs);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Force current map layer to update
|
|
m_nCurrentRadarVerticalSection = -1;
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::FlashUpdateMapLayer( int layerIdx )
|
|
{
|
|
if (m_bFlashReady)
|
|
{
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 1)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, layerIdx);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "setVisibleLayer", args, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::MapLoaded( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
// flash passes in the scaledsize / image size
|
|
m_fMapSize = 320; //radar_mapsize.GetInt();//( float )pui->Params_GetArgAsNumber( obj, 0 );
|
|
|
|
m_fPixelToRadarScale = ( float )pui->Params_GetArgAsNumber( obj, 0 );
|
|
|
|
m_fRadarSize = ( float )pui->Params_GetArgAsNumber( obj, 1 );
|
|
|
|
|
|
m_fWorldToRadarScale = m_fWorldToPixelScale * m_fPixelToRadarScale;
|
|
|
|
V_strcpy_safe( m_cLoadedMapName, m_cDesiredMapName );
|
|
}
|
|
|
|
|
|
/**********************************************
|
|
* reset functions
|
|
*/
|
|
|
|
|
|
void SFHudRadar::ResetForNewMap( void )
|
|
{
|
|
if ( m_bFlashReady )
|
|
{
|
|
for ( int i = 0; i < 2; i++ )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_BombZoneIcons[i], false );
|
|
}
|
|
|
|
for ( int i = 0; i < MAX_HOSTAGE_RESCUES; i++ )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_HostageZoneIcons[i], false );
|
|
}
|
|
|
|
while( m_iLastHostageIndex >= 0 )
|
|
{
|
|
RemoveHostage( m_iLastHostageIndex );
|
|
}
|
|
|
|
int index = 0;
|
|
while( m_HostageStatusIcons[index].m_IconPackage && ( index < MAX_HOSTAGES ) )
|
|
{
|
|
m_HostageStatusIcons[index++].SetStatus( SFHudRadarHostageIcons::HI_UNUSED );
|
|
}
|
|
|
|
RemoveAllDecoys();
|
|
RemoveAllDefusers();
|
|
}
|
|
|
|
m_iNumGoalIcons = 0;
|
|
m_bGotGoalIcons = false;
|
|
|
|
for ( int i = 0; i <= m_iLastPlayerIndex; i++ )
|
|
{
|
|
ResetPlayer( i );
|
|
}
|
|
|
|
ResetRoundVariables();
|
|
|
|
}
|
|
|
|
void SFHudRadar::ResetRoundVariables( bool bResetGlobalStates )
|
|
{
|
|
SetVisibilityFlags( 0 );
|
|
SetLocationText( NULL );
|
|
|
|
m_RadarViewpointWorld = vec3_origin;
|
|
m_RadarViewpointMap = vec3_origin;
|
|
m_RadarRotation = 0;
|
|
m_fBombSeenTime = TIMER_INIT;
|
|
m_fBombAlpha = 0.0f;
|
|
m_fDefuserSeenTime = TIMER_INIT;
|
|
m_fDefuserAlpha = 0.0f;
|
|
m_bShowingHostageZone = false;
|
|
|
|
m_bShowBombHighlight = false;
|
|
m_bShowingDashboard = false;
|
|
m_bShowAll = false;
|
|
m_iObserverMode = OBS_MODE_NONE;
|
|
|
|
ConVarRef mp_defuser_allocation( "mp_defuser_allocation" );
|
|
m_bTrackDefusers = ( mp_defuser_allocation.GetInt() == DefuserAllocation::Random );
|
|
|
|
if ( bResetGlobalStates )
|
|
{
|
|
m_nBombEntIndex = -1;
|
|
m_nBombHolderUserId = -1;
|
|
m_BombPosition = vec3_origin;
|
|
m_DefuserPosition = vec3_origin;
|
|
m_bBombIsSpotted = false;
|
|
m_bBombPlanted = false;
|
|
m_bBombDropped = false;
|
|
m_bBombExploded = false;
|
|
m_bBombDefused = false;
|
|
}
|
|
|
|
m_EntitySpotted.ClearAll();
|
|
}
|
|
|
|
void SFHudRadar::ResetRadar( bool bResetGlobalStates )
|
|
{
|
|
for ( int i = 0; i <= m_iLastPlayerIndex; i++ )
|
|
{
|
|
ResetPlayer( i );
|
|
}
|
|
|
|
if ( CSGameRules()->IsHostageRescueMap() )
|
|
{
|
|
RemoveStaleHostages();
|
|
|
|
for ( int i = 0; i <= m_iLastHostageIndex; i++ )
|
|
{
|
|
ResetHostage( i );
|
|
}
|
|
|
|
int index = 0;
|
|
while( m_HostageStatusIcons[index].m_IconPackage && ( index < MAX_HOSTAGES ) )
|
|
{
|
|
m_HostageStatusIcons[index++].SetStatus( SFHudRadarHostageIcons::HI_UNUSED );
|
|
}
|
|
}
|
|
|
|
if ( bResetGlobalStates )
|
|
{
|
|
RemoveAllDecoys();
|
|
RemoveAllDefusers();
|
|
RemoveAllHostages();
|
|
}
|
|
|
|
ResetRoundVariables( bResetGlobalStates );
|
|
|
|
Show( true );
|
|
}
|
|
|
|
void SFHudRadar::ResetRound( void )
|
|
{
|
|
ResetRadar( true );
|
|
}
|
|
|
|
|
|
/*****************************************************
|
|
* player icon loading / creating
|
|
*/
|
|
|
|
bool SFHudRadar::LazyUpdateIconArray( SFHudRadarIconPackage* pArray, int lastIndex )
|
|
{
|
|
bool result = true;
|
|
int i;
|
|
SFHudRadarIconPackage* pwalk;
|
|
|
|
for ( pwalk = pArray, i = 0; i <= lastIndex; i++, pwalk++ )
|
|
{
|
|
if ( pwalk->m_bIsActive && !pwalk->m_IconPackage )
|
|
{
|
|
if ( !LazyCreateIconPackage( pwalk ) )
|
|
{
|
|
// keep going, but remember that at least one wasn't loaded correctly
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void SFHudRadar::LazyCreatePlayerIcons( void )
|
|
{
|
|
if ( !m_bFlashReady || m_bGotPlayerIcons )
|
|
return;
|
|
|
|
// the following code looks odd, but it insures that all three of the LazyUpdate calls are made
|
|
// even if m_bGotPlayerIcons becomes false early.
|
|
|
|
m_bGotPlayerIcons = LazyUpdateIconArray( m_Players, m_iLastPlayerIndex );
|
|
|
|
m_bGotPlayerIcons = LazyUpdateIconArray( m_Hostages, m_iLastHostageIndex ) && m_bGotPlayerIcons;
|
|
|
|
m_bGotPlayerIcons = LazyUpdateIconArray( m_Decoys, m_iLastDecoyIndex ) && m_bGotPlayerIcons;
|
|
|
|
m_bGotPlayerIcons = LazyUpdateIconArray( m_Defusers, m_iLastDefuserIndex ) && m_bGotPlayerIcons;
|
|
|
|
}
|
|
|
|
bool SFHudRadar::LazyCreateIconPackage( SFHudRadarIconPackage* pIconPack )
|
|
{
|
|
if ( m_bFlashReady && pIconPack->m_bIsActive && !pIconPack->m_IconPackage )
|
|
{
|
|
SFVALUE result = NULL;
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, pIconPack->m_iIndex );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 1, pIconPack->m_IconPackType );
|
|
result = m_pScaleformUI->Value_Invoke( m_IconTranslation, "createIconPack", args, 2 );
|
|
|
|
pIconPack->Init( m_pScaleformUI, result );
|
|
|
|
if ( result )
|
|
{
|
|
m_pScaleformUI->ReleaseValue( result );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::InitIconPackage( SFHudRadarIconPackage* pPlayer, int iAbsoluteIndex, ICON_PACK_TYPE iconType )
|
|
{
|
|
if ( pPlayer->m_bIsActive && m_pScaleformUI )
|
|
{
|
|
RemoveIconPackage( pPlayer );
|
|
}
|
|
|
|
pPlayer->m_IconPackType = iconType;
|
|
pPlayer->m_iIndex = iAbsoluteIndex;
|
|
pPlayer->m_bIsActive = true;
|
|
|
|
pPlayer->StartRound();
|
|
|
|
if ( !pPlayer->m_IconPackage && !LazyCreateIconPackage( pPlayer ) )
|
|
{
|
|
m_bGotPlayerIcons = false;
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudRadar::RemoveIconPackage( SFHudRadarIconPackage* pPackage )
|
|
{
|
|
if ( pPackage->m_bIsActive && m_pScaleformUI )
|
|
{
|
|
if ( m_bFlashReady && pPackage->m_IconPackage )
|
|
{
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, pPackage->m_IconPackage );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IconTranslation, "removeIconPack", args, 1 );
|
|
}
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
pPackage->NukeFromOrbit( this );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************
|
|
* player and hostage initialization and creation
|
|
*/
|
|
|
|
void SFHudRadar::UpdateAllPlayerNumbers( void )
|
|
{
|
|
for ( int i = 0; i <= MAX_PLAYERS; ++i )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( i );
|
|
if ( pPackage )
|
|
UpdatePlayerNumber( pPackage );
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::UpdatePlayerNumber( SFHudRadarIconPackage* pPackage )
|
|
{
|
|
int nMaxPlayers = CCSGameRules::GetMaxPlayers();
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
if ( !pLocalPlayer )
|
|
return;
|
|
|
|
bool bSpec = pLocalPlayer->IsSpectator() || engine->IsHLTV();
|
|
|
|
// update the player number
|
|
SFHudTeamCounter* pTeamCounter = GET_HUDELEMENT( SFHudTeamCounter );
|
|
if ( pPackage && pPackage->m_Icons[PI_PLAYER_NUMBER] )
|
|
{
|
|
if ( pTeamCounter )
|
|
{
|
|
int pidx = pTeamCounter->GetPlayerSlotIndex(pPackage->m_iEntityID);
|
|
if ( pidx != -1 )
|
|
{
|
|
if (bSpec)
|
|
{
|
|
pidx += 1;
|
|
if (pidx == 10)
|
|
pidx = 0;
|
|
|
|
ISFTextObject* textPanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember(pPackage->m_Icons[PI_PLAYER_NUMBER], "Text");
|
|
if (textPanel)
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
if (nMaxPlayers <= 10)
|
|
{
|
|
textPanel->SetText(pidx);
|
|
}
|
|
else
|
|
{
|
|
textPanel->SetText("");
|
|
}
|
|
}
|
|
SafeReleaseSFTextObject(textPanel);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bool bShowLetter = false;
|
|
|
|
if ((pPackage->m_fLastColorUpdate + 0.5f) < gpGlobals->curtime)
|
|
{
|
|
int nOtherTeamNum = 0;
|
|
if (pPackage->m_iPlayerType == PI_CT)
|
|
nOtherTeamNum = TEAM_CT;
|
|
else if (pPackage->m_iPlayerType == PI_T)
|
|
nOtherTeamNum = TEAM_TERRORIST;
|
|
|
|
int nColorID = -1;
|
|
if (pLocalPlayer->ShouldShowTeamPlayerColors(nOtherTeamNum))
|
|
{
|
|
C_CS_PlayerResource* pCSPR = ( C_CS_PlayerResource* )g_PR;
|
|
if ( pCSPR )
|
|
nColorID = pCSPR->GetCompTeammateColor( pPackage->m_iEntityID );
|
|
|
|
bShowLetter = pLocalPlayer->ShouldShowTeamPlayerColorLetters( );
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
if (pPackage->m_iPlayerType == PI_CT && pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT)
|
|
{
|
|
// ScaleformDisplayInfo displayInfo;
|
|
// displayInfo.SetAlpha(100.0f);
|
|
// displayInfo.SetVisibility(1);
|
|
// m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_IconPackage, &displayInfo);
|
|
|
|
SFVALUE doton = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_CT], "Dot");
|
|
SFVALUE dotoff = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_CT_OFFMAP], "Arrow");
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, doton);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, dotoff);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, pPackage->m_Icons[PI_CT_DEAD]);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
SafeReleaseSFVALUE(doton);
|
|
SafeReleaseSFVALUE(dotoff);
|
|
}
|
|
else if (pPackage->m_iPlayerType == PI_T && pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST)
|
|
{
|
|
if (pPackage->m_bIsDead == false && pPackage->m_Health > 0)
|
|
{
|
|
ScaleformDisplayInfo displayInfo;
|
|
displayInfo.SetAlpha(100.0f);
|
|
displayInfo.SetVisibility(1);
|
|
m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_IconPackageRotate, &displayInfo);
|
|
//m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_IconPackage, &displayInfo);
|
|
|
|
SFVALUE doton = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_T], "Dot");
|
|
SFVALUE dotoff = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_T_OFFMAP], "Arrow");
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
//m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_Icons[PI_T], &displayInfo);
|
|
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, doton);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, dotoff);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, pPackage->m_Icons[PI_T_DEAD]);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
SafeReleaseSFVALUE(doton);
|
|
SafeReleaseSFVALUE(dotoff);
|
|
}
|
|
}
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, pPackage->m_Icons[PI_PLAYER_LETTER] );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 1, bShowLetter ? nColorID : -1 );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SetPlayerColorLetter", args, 2 );
|
|
}
|
|
|
|
// decide if the target shows the symbol
|
|
// make sure they're no the other team
|
|
if ( pPackage->m_iPlayerType == PI_ENEMY && Helper_ShouldShowAssassinationTargetIcon( pPackage->m_iEntityID ) )
|
|
{
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
|
|
{
|
|
// unique number for targets for missions
|
|
int nSpecialTargetID = 10;
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, pPackage->m_Icons[PI_PLAYER_LETTER] );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 1, nSpecialTargetID );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SetPlayerColorLetter", args, 2 );
|
|
}
|
|
}
|
|
}
|
|
|
|
pPackage->m_fLastColorUpdate = gpGlobals->curtime;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreatePlayer( int index )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( index );
|
|
InitIconPackage( pPackage, index, ICON_PACK_PLAYER );
|
|
|
|
m_iLastPlayerIndex = MAX( index, m_iLastPlayerIndex );
|
|
|
|
return pPackage;
|
|
}
|
|
|
|
|
|
void SFHudRadar::ResetPlayer( int index )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( index );
|
|
if ( pPackage->m_bIsActive )
|
|
{
|
|
pPackage->StartRound();
|
|
|
|
UpdatePlayerNumber( pPackage );
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::RemovePlayer( int index )
|
|
{
|
|
RemoveIconPackage( GetRadarPlayer( index ) );
|
|
|
|
if ( index == m_iLastPlayerIndex )
|
|
{
|
|
while( m_iLastPlayerIndex >= 0 && !m_Players[m_iLastPlayerIndex].m_bIsActive )
|
|
{
|
|
m_iLastPlayerIndex--;
|
|
}
|
|
}
|
|
|
|
UpdateAllPlayerNumbers();
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreateHostage( int index )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarHostage( index );
|
|
InitIconPackage( pPackage, index, ICON_PACK_HOSTAGE );
|
|
|
|
m_iLastHostageIndex = MAX( index, m_iLastHostageIndex );
|
|
|
|
return pPackage;
|
|
}
|
|
|
|
void SFHudRadar::ResetHostage( int index )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarHostage( index );
|
|
if ( pPackage->m_bIsActive )
|
|
{
|
|
pPackage->StartRound();
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::RemoveAllHostages( void )
|
|
{
|
|
for ( int index = 0; index < MAX_HOSTAGES; index++ )
|
|
{
|
|
RemoveHostage( index );
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::RemoveStaleHostages( void )
|
|
{
|
|
// Remove hostages that are no longer tracked by the player resource (hostages that have died)
|
|
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
if ( !pCSPR )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( int index = 0; index < MAX_HOSTAGES; index++ )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarHostage( index );
|
|
if ( pPackage->m_bIsActive )
|
|
{
|
|
bool bRemove = true;
|
|
|
|
for( int i = 0; i < MAX_HOSTAGES; i++ )
|
|
{
|
|
if ( pCSPR->GetHostageEntityID( i ) == pPackage->m_iEntityID )
|
|
{
|
|
bRemove = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( bRemove )
|
|
{
|
|
RemoveHostage( index );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::RemoveHostage( int index )
|
|
{
|
|
RemoveIconPackage( GetRadarHostage( index ) );
|
|
|
|
if ( index == m_iLastHostageIndex )
|
|
{
|
|
while( m_iLastHostageIndex >= 0 && !m_Hostages[m_iLastHostageIndex].m_bIsActive )
|
|
{
|
|
m_iLastHostageIndex--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreateDecoy( int entityID )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = NULL;
|
|
int index = m_iLastDecoyIndex+1;
|
|
|
|
for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
|
|
{
|
|
if ( !m_Decoys[i].m_bIsActive )
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( index < MAX_DECOYS )
|
|
{
|
|
pPackage = GetRadarDecoy( index );
|
|
|
|
InitIconPackage( pPackage, index, ICON_PACK_DECOY );
|
|
|
|
pPackage->m_iEntityID = entityID;
|
|
pPackage->m_fRoundStartTime = TIMER_INIT;
|
|
|
|
m_iLastDecoyIndex = MAX( index, m_iLastDecoyIndex );
|
|
}
|
|
|
|
return pPackage;
|
|
}
|
|
|
|
void SFHudRadar::RemoveAllDecoys( void )
|
|
{
|
|
for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
|
|
{
|
|
if ( m_Decoys[i].m_bIsActive )
|
|
{
|
|
RemoveDecoy( i );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SFHudRadar::RemoveDecoy( int index )
|
|
{
|
|
RemoveIconPackage( GetRadarDecoy( index ) );
|
|
|
|
if ( index == m_iLastDecoyIndex )
|
|
{
|
|
while( m_iLastDecoyIndex >= 0 && !m_Decoys[m_iLastDecoyIndex].m_bIsActive )
|
|
{
|
|
m_iLastDecoyIndex--;
|
|
}
|
|
}
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarIconPackage * SFHudRadar::GetDefuser( int nEntityID, bool bCreateIfNotFound )
|
|
{
|
|
SFHudRadarIconPackage * pResult = NULL;
|
|
|
|
int nIndex = GetDefuseIndexFromEntityID( nEntityID );
|
|
|
|
if ( nIndex != INVALID_INDEX )
|
|
{
|
|
pResult = GetRadarDefuser( nIndex );
|
|
}
|
|
|
|
if ( pResult == NULL && bCreateIfNotFound )
|
|
{
|
|
pResult = CreateDefuser( nEntityID );
|
|
}
|
|
|
|
return pResult;
|
|
}
|
|
|
|
|
|
|
|
void SFHudRadar::SetDefuserPos( int nEntityID, int x, int y, int z, int a )
|
|
{
|
|
if ( !m_bTrackDefusers )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarIconPackage * pDefuser = GetDefuser( nEntityID, true );
|
|
|
|
AssertMsg( pDefuser != NULL, "Defuser not found. Update failed." );
|
|
|
|
if ( pDefuser )
|
|
{
|
|
pDefuser->m_Position.Init( x, y, z ) ;
|
|
pDefuser->SetAlpha( 1.0f );
|
|
|
|
SetIconPackagePosition( pDefuser );
|
|
}
|
|
}
|
|
|
|
// defusers attached to players will update during the PlacePlayer phase
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreateDefuser( int nEntityID )
|
|
{
|
|
if ( !m_bTrackDefusers )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SFHudRadarIconPackage* pPackage = NULL;
|
|
int index = m_iLastDefuserIndex+1;
|
|
|
|
AssertMsg( GetDefuseIndexFromEntityID( nEntityID ) == INVALID_INDEX, "Defuser entity ID already exists." );
|
|
|
|
for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
|
|
{
|
|
if ( !m_Defusers[i].m_bIsActive )
|
|
{
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( index < MAX_PLAYERS )
|
|
{
|
|
pPackage = GetRadarDefuser( index );
|
|
|
|
InitIconPackage( pPackage, index, ICON_PACK_DEFUSER );
|
|
|
|
pPackage->m_iEntityID = nEntityID;
|
|
pPackage->m_fRoundStartTime = TIMER_INIT;
|
|
pPackage->SetIsSpotted( false );
|
|
pPackage->SetIsDefuse( true );
|
|
pPackage->m_Position = vec3_origin;
|
|
|
|
m_iLastDefuserIndex = MAX( index, m_iLastDefuserIndex );
|
|
}
|
|
else
|
|
{
|
|
AssertMsg( false, "m_Defusers array is full" );
|
|
}
|
|
|
|
return pPackage;
|
|
}
|
|
|
|
void SFHudRadar::RemoveAllDefusers( void )
|
|
{
|
|
for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
|
|
{
|
|
if ( m_Defusers[i].m_bIsActive )
|
|
{
|
|
RemoveDefuser( i );
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::RemoveDefuser( int index )
|
|
{
|
|
RemoveIconPackage( GetRadarDefuser( index ) );
|
|
|
|
if ( index == m_iLastDefuserIndex )
|
|
{
|
|
while( m_iLastDefuserIndex >= 0 && !m_Defusers[m_iLastDefuserIndex].m_bIsActive )
|
|
{
|
|
m_iLastDefuserIndex--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void SFHudRadar::SetPlayerTeam( int index, int team )
|
|
{
|
|
SFHudRadarIconPackage* pPlayer = GetRadarPlayer( index );
|
|
pPlayer->SetPlayerTeam( team );
|
|
}
|
|
|
|
int SFHudRadar::GetPlayerIndexFromUserID( int userID )
|
|
{
|
|
int nEntityID = engine->GetPlayerForUserID( userID );
|
|
for ( int i = 0; i <= m_iLastPlayerIndex; i++ )
|
|
{
|
|
if ( m_Players[i].m_bIsActive && m_Players[i].m_iEntityID == nEntityID )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return INVALID_INDEX;
|
|
}
|
|
|
|
int SFHudRadar::GetHostageIndexFromHostageEntityID( int entityID )
|
|
{
|
|
for ( int i = 0; i <= m_iLastHostageIndex; i++ )
|
|
{
|
|
if ( m_Hostages[i].m_bIsActive && m_Hostages[i].m_iEntityID == entityID )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return INVALID_INDEX;
|
|
}
|
|
|
|
int SFHudRadar::GetDecoyIndexFromEntityID( int entityID )
|
|
{
|
|
for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
|
|
{
|
|
if ( m_Decoys[i].m_bIsActive && m_Decoys[i].m_iEntityID == entityID )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return INVALID_INDEX;
|
|
}
|
|
|
|
int SFHudRadar::GetDefuseIndexFromEntityID( int nEntityID )
|
|
{
|
|
for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
|
|
{
|
|
if ( m_Defusers[i].m_bIsActive && m_Defusers[i].m_iEntityID == nEntityID )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return INVALID_INDEX;
|
|
}
|
|
|
|
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarPlayer( int index )
|
|
{
|
|
return &m_Players[index];
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarHostage( int index )
|
|
{
|
|
return &m_Hostages[index];
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarDecoy( int index )
|
|
{
|
|
return &m_Decoys[index];
|
|
}
|
|
|
|
SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarDefuser( int index )
|
|
{
|
|
return &m_Defusers[index];
|
|
}
|
|
|
|
/*************************************************
|
|
* We don't get updates from the server from players
|
|
* that are not in our PVS, so there are separate
|
|
* messages specifically to update the radar
|
|
*/
|
|
bool SFHudRadar::MsgFunc_ProcessSpottedEntityUpdate( const CCSUsrMsg_ProcessSpottedEntityUpdate &msg )
|
|
{
|
|
if ( msg.new_update() )
|
|
{
|
|
// new spotting frame. clean up.
|
|
m_bBombIsSpotted = false;
|
|
m_EntitySpotted.ClearAll();
|
|
}
|
|
|
|
for ( int i = 0; i < msg.entity_updates_size(); i ++ )
|
|
{
|
|
const CCSUsrMsg_ProcessSpottedEntityUpdate::SpottedEntityUpdate &update = msg.entity_updates(i);
|
|
|
|
int nEntityID = update.entity_idx();
|
|
if ( nEntityID < 0 || nEntityID >= MAX_EDICTS )
|
|
continue; // GeekPwn2016 range check
|
|
|
|
// non-class specific data
|
|
// read position and angle
|
|
int x = update.origin_x() * 4;
|
|
int y = update.origin_y() * 4;
|
|
int z = update.origin_z() * 4;
|
|
int a = update.angle_y();
|
|
|
|
m_EntitySpotted.Set( nEntityID, true );
|
|
|
|
const char * szEntityClass = NULL;
|
|
|
|
int nClassID = update.class_id();
|
|
for ( ClientClass *pCur = g_pClientClassHead; pCur; pCur=pCur->m_pNext )
|
|
{
|
|
if ( pCur->m_ClassID == nClassID )
|
|
{
|
|
szEntityClass = pCur->GetName();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( szEntityClass == NULL )
|
|
{
|
|
Warning( "Unknown entity class received in ProcessSpottedEntityUpdate.\n" );
|
|
}
|
|
|
|
// Clients are unaware of the defuser class type, so we need to flag defuse entities manually
|
|
if ( update.defuser() )
|
|
{
|
|
SetDefuserPos( nEntityID, x, y, z, a );
|
|
}
|
|
else if ( V_strcmp( "CCSPlayer", szEntityClass ) == 0 )
|
|
{
|
|
SFHudRadarIconPackage* pPlayerIcon = NULL;
|
|
|
|
pPlayerIcon = GetRadarPlayer( nEntityID - 1 );
|
|
|
|
if ( pPlayerIcon->m_bIsDead )
|
|
continue;
|
|
|
|
pPlayerIcon->m_Position.Init( x, y, z );
|
|
pPlayerIcon->m_Angle.Init( 0, a, 0 );
|
|
|
|
// has defuser?
|
|
if ( update.player_has_defuser() )
|
|
{
|
|
SetDefuserPos( nEntityID, x, y, z, a );
|
|
}
|
|
|
|
// has C4?
|
|
if ( update.player_has_c4() )
|
|
{
|
|
m_bBombIsSpotted = true;
|
|
m_BombPosition.Init( x, y, 0 );
|
|
}
|
|
|
|
// The following code should no longer be necessary with the new spotting system
|
|
//C_CSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( nEntityID ) );
|
|
|
|
//// Only update players that are outside of PVS
|
|
//if ( pPlayer && pPlayer->IsDormant() )
|
|
//{
|
|
// // update origin and angle for players out of my PVS
|
|
// Vector origin = pPlayer->GetAbsOrigin();
|
|
// QAngle angles = pPlayer->GetAbsAngles();
|
|
|
|
// origin.x = x;
|
|
// origin.y = y;
|
|
// angles.y = a;
|
|
|
|
// pPlayer->SetAbsOrigin( origin );
|
|
// pPlayer->SetAbsAngles( angles );
|
|
//}
|
|
}
|
|
else if ( V_strcmp( "CC4", szEntityClass ) == 0 || V_strcmp( "CPlantedC4", szEntityClass ) == 0 )
|
|
{
|
|
m_bBombIsSpotted = true;
|
|
m_BombPosition.Init( x, y, 0 );
|
|
}
|
|
else if ( V_strcmp( "CHostage", szEntityClass ) == 0 )
|
|
{
|
|
int hostageIndex = GetHostageIndexFromHostageEntityID( nEntityID );
|
|
|
|
if ( hostageIndex == INVALID_INDEX )
|
|
{
|
|
for ( int i = 0; i <= m_iLastHostageIndex; i++ )
|
|
{
|
|
RemoveHostage( i );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarHostage( hostageIndex );
|
|
|
|
if ( pPackage )
|
|
{
|
|
pPackage->m_Position.Init( x, y, z );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Warning( "Unknown entity update received by ProcessSpottedEntityUpdate: %s.\n", szEntityClass );
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// handles all game event messages ( first looks them up in map so there's no long list of strcmps )
|
|
void SFHudRadar::FireGameEvent( IGameEvent *event )
|
|
{
|
|
const char* eventName = event->GetName();
|
|
int elementIndex = m_messageMap.Find( eventName );
|
|
if ( elementIndex == m_messageMap.InvalidIndex() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SF_SPLITSCREEN_PLAYER_GUARD();
|
|
|
|
|
|
DESIRED_MESSAGE_INDICES messageTypeIndex = ( DESIRED_MESSAGE_INDICES )m_messageMap.Element( elementIndex );
|
|
|
|
switch( messageTypeIndex )
|
|
{
|
|
case GAME_NEWMAP:
|
|
ResetForNewMap();
|
|
SetMap( event->GetString( "mapname" ) );
|
|
break;
|
|
|
|
case ROUND_POST_START:
|
|
{
|
|
ResetRound();
|
|
UpdateAllPlayerNumbers();
|
|
}
|
|
break;
|
|
|
|
case PLAYER_CONNECT:
|
|
case PLAYER_INFO:
|
|
{
|
|
int index = event->GetInt( "index" ); // = entity index - 1
|
|
int userID = index + 1;
|
|
|
|
if ( index < 0 || index >= MAX_PLAYERS )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarIconPackage* pPackage = CreatePlayer( index );
|
|
if ( messageTypeIndex == PLAYER_CONNECT )
|
|
{
|
|
pPackage->SetPlayerTeam( TEAM_SPECTATOR );
|
|
}
|
|
|
|
pPackage->m_iEntityID = userID;
|
|
|
|
const char* name = event->GetString( "name","unknown" );
|
|
|
|
V_UTF8ToUnicode( name, pPackage->m_wcName, sizeof( pPackage->m_wcName ) );
|
|
}
|
|
break;
|
|
|
|
case PLAYER_TEAM:
|
|
{
|
|
int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
|
|
|
|
if ( playerIndex == INVALID_INDEX )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( playerIndex );
|
|
pPackage->SetPlayerTeam( event->GetInt( "team" ) );
|
|
UpdatePlayerNumber( pPackage );
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if ( pLocalPlayer )
|
|
{
|
|
int localID = pLocalPlayer->GetUserID();
|
|
if ( localID == playerIndex )
|
|
{
|
|
ResizeHud();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PLAYER_DEATH:
|
|
{
|
|
int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
|
|
|
|
if ( playerIndex == INVALID_INDEX )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( playerIndex );
|
|
|
|
if ( pPackage->m_bIsActive )
|
|
{
|
|
pPackage->SetIsDead( true );
|
|
pPackage->m_Health = 0;
|
|
}
|
|
|
|
int nDefuseIndex = GetDefuseIndexFromEntityID( engine->GetPlayerForUserID( event->GetInt( "userid" ) ) );
|
|
|
|
if ( nDefuseIndex != INVALID_INDEX )
|
|
{
|
|
RemoveDefuser( nDefuseIndex );
|
|
}
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if ( pLocalPlayer )
|
|
{
|
|
int localID = pLocalPlayer->GetUserID();
|
|
if ( localID == playerIndex )
|
|
{
|
|
ResizeHud();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PLAYER_SPAWN:
|
|
{
|
|
int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
|
|
|
|
if ( playerIndex != INVALID_INDEX )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer( playerIndex );
|
|
pPackage->m_Health = 100;
|
|
|
|
UpdatePlayerNumber( pPackage );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PLAYER_DISCONNECT:
|
|
{
|
|
|
|
int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
|
|
|
|
if ( playerIndex != INVALID_INDEX )
|
|
{
|
|
RemovePlayer( playerIndex );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case HOSTAGE_KILLED:
|
|
{
|
|
int hostageIndex = GetHostageIndexFromHostageEntityID( event->GetInt( "hostage" ) );
|
|
|
|
if ( hostageIndex == INVALID_INDEX )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarIconPackage* pPackage = GetRadarHostage( hostageIndex );
|
|
|
|
if ( pPackage->m_bIsActive )
|
|
{
|
|
pPackage->SetIsDead( true );
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case HOSTAGE_RESCUED:
|
|
{
|
|
int hostageIndex = GetHostageIndexFromHostageEntityID( event->GetInt( "hostage" ) );
|
|
|
|
if ( hostageIndex == INVALID_INDEX )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarIconPackage* pPackage = GetRadarHostage( hostageIndex );
|
|
|
|
if ( pPackage->m_bIsActive )
|
|
{
|
|
pPackage->SetIsRescued( true );
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case BOMB_DEFUSED:
|
|
{
|
|
m_bBombDefused = true;
|
|
}
|
|
break;
|
|
|
|
case BOMB_EXPLODED:
|
|
{
|
|
m_bBombExploded = true;
|
|
}
|
|
break;
|
|
|
|
case BOMB_PLANTED:
|
|
{
|
|
m_nBombEntIndex = -1;
|
|
m_bBombPlanted = true;
|
|
m_BombPosition.z = 0;
|
|
m_nBombHolderUserId = -1;
|
|
}
|
|
break;
|
|
|
|
case BOMB_PICKUP:
|
|
{
|
|
m_bBombDropped = false;
|
|
m_nBombEntIndex = -1;
|
|
m_nBombHolderUserId = event->GetInt( "userid", -1 );
|
|
}
|
|
break;
|
|
|
|
case BOMB_DROPPED:
|
|
{
|
|
m_nBombEntIndex = event->GetInt( "entindex", -1 );
|
|
m_bBombDropped = true;
|
|
m_nBombHolderUserId = -1;
|
|
}
|
|
break;
|
|
|
|
case DEFUSER_PICKUP:
|
|
{
|
|
int nDefuseIndex = GetDefuseIndexFromEntityID( event->GetInt( "entityid" ) );
|
|
|
|
if ( nDefuseIndex != INVALID_INDEX )
|
|
{
|
|
RemoveDefuser( nDefuseIndex );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DEFUSER_DROPPED:
|
|
{
|
|
int nEntityID = event->GetInt( "entityid" );
|
|
|
|
CreateDefuser( nEntityID );
|
|
}
|
|
break;
|
|
|
|
case DECOY_STARTED:
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if ( pLocalPlayer )
|
|
{
|
|
int userID = event->GetInt( "userid" );
|
|
CBasePlayer* player = UTIL_PlayerByUserId( userID );
|
|
|
|
if ( player )
|
|
{
|
|
// the radar only shows the enemy decoys
|
|
if ( pLocalPlayer->IsOtherEnemy( player->entindex() ) )
|
|
{
|
|
int entityID = event->GetInt( "entityid" );
|
|
int teamNumber = player->GetAssociatedTeamNumber();
|
|
|
|
SFHudRadarIconPackage* pPackage = CreateDecoy( entityID );
|
|
|
|
if ( pPackage )
|
|
{
|
|
pPackage->SetPlayerTeam( teamNumber );
|
|
pPackage->SetIsSpotted( true );
|
|
// this sets the exact moment when the grenade should no longer be visible incase we miss the event
|
|
pPackage->SetGrenadeExpireTime( gpGlobals->curtime + 24 );
|
|
|
|
pPackage->m_Position.Init( ( float )event->GetInt( "x" ), ( float )event->GetInt( "y" ), 0.0f );
|
|
pPackage->m_Angle.Init( 0.0f, RandomFloat( 0.0f, 360.0f ), 0.0f );
|
|
SetIconPackagePosition( pPackage );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case DECOY_DETONATE:
|
|
{
|
|
int entityID = event->GetInt( "entityid" );
|
|
int i = GetDecoyIndexFromEntityID( entityID );
|
|
if ( i != INVALID_INDEX )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarDecoy( i );
|
|
pPackage->SetIsSpotted( false );
|
|
SetIconPackagePosition( pPackage );
|
|
}
|
|
|
|
STEAMWORKS_TESTSECRET_AMORTIZE( 31 );
|
|
}
|
|
break;
|
|
|
|
case BOT_TAKEOVER:
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if ( pLocalPlayer )
|
|
{
|
|
int userID = event->GetInt( "userid" );
|
|
//int playerIndex = GetPlayerIndexFromUserID(event->GetInt("userid"));
|
|
int localID = pLocalPlayer->GetUserID();
|
|
|
|
if (localID == userID )
|
|
{
|
|
ResizeHud();
|
|
ResetRadar( false );
|
|
|
|
int playerIndex = GetPlayerIndexFromUserID(userID);
|
|
if (playerIndex != INVALID_INDEX)
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarPlayer(playerIndex);
|
|
UpdatePlayerNumber(pPackage);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************
|
|
* these set lazy update the icons and text based
|
|
* on the values in the state variables
|
|
*/
|
|
|
|
void SFHudRadar::SetupIconsFromStates( void )
|
|
{
|
|
int newFlags = 0;
|
|
|
|
if ( CSGameRules()->IsBombDefuseMap() )
|
|
{
|
|
if ( m_fBombAlpha > 0.0f )
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
newFlags |= 1 << RI_BOMB_ICON_PACKAGE;
|
|
if ( m_bShowBombHighlight )
|
|
{
|
|
if ( m_bBombPlanted )
|
|
{
|
|
newFlags |= 1 << RI_BOMB_ICON_PLANTED;
|
|
}
|
|
else
|
|
{
|
|
newFlags |= 1 << RI_BOMB_ICON_DROPPED;
|
|
}
|
|
|
|
C_CSPlayer *pLocalOrObserver = NULL;
|
|
if ( pLocalPlayer )
|
|
{
|
|
C_BaseEntity *target = pLocalPlayer->GetObserverTarget();
|
|
if( target && target->IsPlayer() )
|
|
pLocalOrObserver = ToCSPlayer( target );
|
|
else
|
|
pLocalOrObserver = pLocalPlayer;
|
|
}
|
|
|
|
if ( pLocalOrObserver )
|
|
{
|
|
if ( m_BombPosition.z > pLocalOrObserver->GetAbsOrigin().z + ABOVE_BELOW_HEIGHT )
|
|
newFlags |= 1 << RI_BOMB_ICON_BOMB_ABOVE;
|
|
else if ( m_BombPosition.z < pLocalOrObserver->GetAbsOrigin().z - ABOVE_BELOW_HEIGHT )
|
|
newFlags |= 1 << RI_BOMB_ICON_BOMB_BELOW;
|
|
}
|
|
}
|
|
|
|
if( pLocalPlayer != NULL )
|
|
{
|
|
if ( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST )
|
|
{
|
|
newFlags |= 1 << RI_BOMB_ICON_BOMB_T;
|
|
}
|
|
else
|
|
{
|
|
newFlags |= 1 << RI_BOMB_ICON_BOMB_CT;
|
|
}
|
|
}
|
|
|
|
Vector mapPosition;
|
|
|
|
WorldToRadar( m_BombPosition, mapPosition );
|
|
|
|
Vector newMapPosition = mapPosition;
|
|
newMapPosition -= m_RadarViewpointMap;
|
|
float dist = newMapPosition.LengthSqr();
|
|
if ( dist >= RADARRADIUS*RADARRADIUS && m_bRound )
|
|
{
|
|
newMapPosition *= sqrt( RADARRADIUS*RADARRADIUS/dist );
|
|
mapPosition = m_RadarViewpointMap;
|
|
mapPosition += newMapPosition;
|
|
}
|
|
|
|
ScaleformDisplayInfo displayInfo;
|
|
displayInfo.SetAlpha( m_fBombAlpha * 100.0f );
|
|
if ( cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
Vector hudPos;
|
|
RadarToHud( mapPosition, hudPos );
|
|
displayInfo.SetX( hudPos.x );
|
|
displayInfo.SetY( hudPos.y );
|
|
displayInfo.SetRotation( 0 );
|
|
}
|
|
else
|
|
{
|
|
displayInfo.SetX( mapPosition.x );
|
|
displayInfo.SetY( mapPosition.y );
|
|
|
|
bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
|
|
displayInfo.SetRotation( bRotate ? -m_RadarRotation : 0 );
|
|
}
|
|
|
|
assert( m_Icons[RI_BOMB_ICON_PACKAGE] );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_Icons[RI_BOMB_ICON_PACKAGE], &displayInfo );
|
|
|
|
SFHudTeamCounter* pTeamCounter = GET_HUDELEMENT( SFHudTeamCounter );
|
|
if (pLocalPlayer && pTeamCounter && m_Icons[RI_BOMB_ICON_PACKAGE])
|
|
{
|
|
int playerIndex = GetPlayerIndexFromUserID( m_nBombHolderUserId ) + 1;
|
|
int pidx = pTeamCounter->GetPlayerSlotIndex( playerIndex );
|
|
|
|
int nColorID = 4;
|
|
if (pLocalPlayer->ShouldShowTeamPlayerColors(pLocalPlayer->GetAssociatedTeamNumber()))
|
|
{
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
|
|
if ( m_bBombDropped == false && ( pidx > -1 ) && pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST )
|
|
{
|
|
if ( pCSPR )
|
|
nColorID = pCSPR->GetCompTeammateColor( playerIndex );
|
|
}
|
|
else
|
|
nColorID = -1;
|
|
}
|
|
|
|
SFVALUE bomb = m_pScaleformUI->Value_GetMember(m_Icons[RI_BOMB_ICON_PACKAGE], "BombT");
|
|
if (bomb)
|
|
{
|
|
SFVALUE bombinner = m_pScaleformUI->Value_GetMember(bomb, "bomb_inner");
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement(args, 0, bombinner);
|
|
m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
|
|
m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
|
|
}
|
|
SafeReleaseSFVALUE(bombinner);
|
|
}
|
|
SafeReleaseSFVALUE(bomb);
|
|
|
|
}
|
|
}
|
|
}
|
|
else if ( CSGameRules()->IsHostageRescueMap() )
|
|
{
|
|
if ( m_bShowingHostageZone )
|
|
{
|
|
newFlags |= 1 << RI_IN_HOSTAGE_ZONE;
|
|
}
|
|
}
|
|
|
|
if ( m_bShowingDashboard )
|
|
newFlags |= 1 << RI_DASHBOARD;
|
|
|
|
SetVisibilityFlags( newFlags );
|
|
}
|
|
|
|
void SFHudRadar::SetVisibilityFlags( int newFlags )
|
|
{
|
|
newFlags &= ( ( 1 << RI_NUM_ICONS )-1 );
|
|
|
|
int diffFlags = m_iCurrentVisibilityFlags ^ newFlags;
|
|
|
|
if ( diffFlags )
|
|
{
|
|
for ( int i = 0; i < RI_NUM_ICONS && ( diffFlags != 0 ); i++, diffFlags >>= 1 )
|
|
{
|
|
if ( diffFlags & 1 )
|
|
{
|
|
if ( m_Icons[i] )
|
|
m_pScaleformUI->Value_SetVisible( m_Icons[i], ( newFlags & ( 1 << i ) ) != 0 );
|
|
}
|
|
}
|
|
|
|
m_iCurrentVisibilityFlags = newFlags;
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::SetLocationText( wchar_t *newText )
|
|
{
|
|
if ( newText == NULL )
|
|
{
|
|
newText = L"";
|
|
}
|
|
|
|
if ( V_wcscmp( newText, m_wcLocationString ) )
|
|
{
|
|
V_wcsncpy( m_wcLocationString, newText, sizeof( wchar_t )*MAX_LOCATION_TEXT_LENGTH );
|
|
|
|
if ( m_LocationText )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_LocationText->SetText( m_wcLocationString );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************
|
|
* "drawing" code. Actually just sets position / alpha
|
|
* of the flash objects
|
|
*/
|
|
|
|
void SFHudRadar::WorldToRadar( const Vector& ptin, Vector& ptout )
|
|
{
|
|
float fWorldScale = m_fWorldToRadarScale;
|
|
|
|
float flMapScaler = 0;
|
|
if ( m_bRound && CSGameRules()->IsPlayingCoopMission() && cl_radar_always_centered.GetBool() )
|
|
flMapScaler = MAX( 0 , (0.75f - fWorldScale) ) * 2.5;
|
|
|
|
float fScale = m_bRound ? (cl_radar_scale.GetFloat() + flMapScaler) : ( m_fRadarSize / m_fMapSize ) ;
|
|
|
|
fWorldScale *= fScale;
|
|
|
|
ptout.x = ( ptin.x - m_MapOrigin.x ) * fWorldScale;
|
|
ptout.y = ( m_MapOrigin.y - ptin.y ) * fWorldScale;
|
|
ptout.z = 0;
|
|
}
|
|
|
|
void SFHudRadar::RadarToHud( const Vector& ptin, Vector& ptout )
|
|
{
|
|
VMatrix rot;
|
|
MatrixBuildRotateZ( rot, m_RadarRotation );
|
|
Vector3DMultiply( rot, ptin - m_RadarViewpointMap, ptout );
|
|
}
|
|
|
|
//ConVar radar_test( "radar_test", "0" );
|
|
|
|
void SFHudRadar::PositionRadarViewpoint( void )
|
|
{
|
|
if ( !m_bFlashReady )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
|
|
|
CBasePlayer * pPlayer = CBasePlayer::GetLocalPlayer();
|
|
|
|
if( pPlayer == NULL )
|
|
{
|
|
pPlayer = GetSplitScreenViewPlayer( nSlot );
|
|
}
|
|
|
|
bool bRotate;
|
|
float fScale;
|
|
Vector vRadarOffset;
|
|
float fFrustrumRotation;
|
|
|
|
Vector vMapCenter = Vector( m_fMapSize / 2, m_fMapSize / 2, 0 );
|
|
|
|
if ( m_bRound )
|
|
{
|
|
// [jbright] Using GetLocalOrigin addresses an issue which
|
|
// causes the center player indicator to not stay centered
|
|
// on the radar. This solution causes the radar to go jump
|
|
// around while in observer mode, so in those cases rely on
|
|
// MainViewOrigin.
|
|
if ( pPlayer && m_iObserverMode == OBS_MODE_NONE )
|
|
{
|
|
m_RadarViewpointWorld = pPlayer->GetLocalOrigin();
|
|
}
|
|
else
|
|
{
|
|
m_RadarViewpointWorld = MainViewOrigin( nSlot );
|
|
}
|
|
|
|
m_RadarViewpointWorld.z = 0;
|
|
|
|
WorldToRadar( m_RadarViewpointWorld, m_RadarViewpointMap );
|
|
|
|
float flMapScaler = 0;
|
|
if ( m_bRound && CSGameRules()->IsPlayingCoopMission() && cl_radar_always_centered.GetBool() )
|
|
flMapScaler = MAX( 0, ( 0.75f - m_fWorldToRadarScale ) ) * 2.5;
|
|
|
|
fScale = cl_radar_scale.GetFloat() + flMapScaler;
|
|
|
|
if ( !cl_radar_always_centered.GetBool() )
|
|
{
|
|
vRadarOffset = ( 1 - fScale ) * ( m_RadarViewpointMap - fScale * ( vMapCenter ) );
|
|
|
|
m_RadarViewpointMap -= vRadarOffset;
|
|
}
|
|
|
|
bRotate = cl_radar_rotate.GetBool();
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
bRotate = false;
|
|
|
|
fScale = m_fRadarSize / m_fMapSize;
|
|
|
|
m_RadarViewpointMap = fScale * vMapCenter;
|
|
|
|
vRadarOffset = Vector( 0, 0, 0 );
|
|
}
|
|
|
|
if ( bRotate )
|
|
{
|
|
m_RadarRotation = MainViewAngles( nSlot )[YAW] - 90;
|
|
fFrustrumRotation = 0;
|
|
}
|
|
else
|
|
{
|
|
m_RadarRotation = 0;
|
|
fFrustrumRotation = MainViewAngles( nSlot )[YAW] - 90;
|
|
}
|
|
|
|
ScaleformDisplayInfo displayInfo;
|
|
|
|
if ( m_MapRotation )
|
|
{
|
|
displayInfo.SetRotation( m_RadarRotation );
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_MapRotation, &displayInfo );
|
|
|
|
if ( m_MapTranslation )
|
|
{
|
|
displayInfo.Clear();
|
|
|
|
displayInfo.SetX( -m_RadarViewpointMap.x );
|
|
displayInfo.SetY( -m_RadarViewpointMap.y );
|
|
|
|
double scale = 100.0f;
|
|
|
|
scale *= fScale;
|
|
|
|
displayInfo.SetXScale( scale );
|
|
displayInfo.SetYScale( scale );
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_MapTranslation, &displayInfo );
|
|
}
|
|
}
|
|
|
|
static bool s_bResetTransform = false;
|
|
if ( m_IconRotation )
|
|
{
|
|
displayInfo.Clear();
|
|
|
|
if ( !cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
displayInfo.SetRotation( m_RadarRotation );
|
|
s_bResetTransform = true;
|
|
}
|
|
else if ( s_bResetTransform )
|
|
{
|
|
// Icons are updated individually (do not update parent)
|
|
displayInfo.SetRotation( 0.0f );
|
|
}
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_IconRotation, &displayInfo );
|
|
|
|
if ( m_IconTranslation )
|
|
{
|
|
displayInfo.Clear();
|
|
|
|
if ( !cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
displayInfo.SetX( -m_RadarViewpointMap.x );
|
|
displayInfo.SetY( -m_RadarViewpointMap.y );
|
|
s_bResetTransform = true;
|
|
}
|
|
else if ( s_bResetTransform )
|
|
{
|
|
// Icons are updated individually (do not update parent)
|
|
displayInfo.SetX( -0.4f );
|
|
displayInfo.SetY( -0.4f );
|
|
}
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_IconTranslation, &displayInfo );
|
|
}
|
|
|
|
if ( cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
s_bResetTransform = false;
|
|
}
|
|
}
|
|
|
|
if ( m_vecRadarVerticalSections.Count() )
|
|
{
|
|
float flPlayerZ = 0;
|
|
if ( pPlayer && m_iObserverMode == OBS_MODE_NONE )
|
|
{
|
|
flPlayerZ = pPlayer->GetLocalOrigin().z;
|
|
}
|
|
else
|
|
{
|
|
flPlayerZ = MainViewOrigin( nSlot ).z;
|
|
}
|
|
|
|
FOR_EACH_VEC( m_vecRadarVerticalSections, i )
|
|
{
|
|
HudRadarLevelVerticalSection_t *pRadarSection = &m_vecRadarVerticalSections[i];
|
|
|
|
if ( flPlayerZ >= pRadarSection->m_flSectionAltitudeFloor &&
|
|
flPlayerZ < pRadarSection->m_flSectionAltitudeCeiling &&
|
|
m_nCurrentRadarVerticalSection != pRadarSection->m_nSectionIndex )
|
|
{
|
|
m_nCurrentRadarVerticalSection = pRadarSection->m_nSectionIndex;
|
|
|
|
FlashUpdateMapLayer(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudRadar::PlaceGoalIcons( void )
|
|
{
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
if ( !pCSPR )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SFHudRadarGoalIcon* pwalk = m_GoalIcons;
|
|
Vector mapPosition;
|
|
ScaleformDisplayInfo displayInfo;
|
|
|
|
bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
|
|
|
|
for ( int i = 0; i < m_iNumGoalIcons; i++ )
|
|
{
|
|
WorldToRadar( pwalk->m_Position, mapPosition );
|
|
|
|
if ( pwalk->m_Icon )
|
|
{
|
|
Vector newMapPosition = mapPosition;
|
|
newMapPosition -= m_RadarViewpointMap;
|
|
float dist = newMapPosition.LengthSqr();
|
|
if ( dist > RADARRADIUS*RADARRADIUS && m_bRound )
|
|
{
|
|
newMapPosition *= sqrt( RADARRADIUS*RADARRADIUS/dist );
|
|
mapPosition = m_RadarViewpointMap;
|
|
mapPosition += newMapPosition;
|
|
}
|
|
|
|
if ( cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
Vector hudPos;
|
|
RadarToHud(mapPosition, hudPos);
|
|
|
|
displayInfo.SetX( hudPos.x );
|
|
displayInfo.SetY( hudPos.y );
|
|
|
|
displayInfo.SetRotation( 0.0f );
|
|
}
|
|
else
|
|
{
|
|
displayInfo.SetX( mapPosition.x );
|
|
displayInfo.SetY( mapPosition.y );
|
|
|
|
displayInfo.SetRotation( bRotate ? -m_RadarRotation : 0 );
|
|
}
|
|
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( pwalk->m_Icon, &displayInfo );
|
|
}
|
|
pwalk++;
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudRadar::SetIconPackagePosition( SFHudRadarIconPackage* pPackage )
|
|
{
|
|
if ( !m_bFlashReady )
|
|
return;
|
|
|
|
Vector mapPosition;
|
|
float mapAngle;
|
|
|
|
WorldToRadar( pPackage->m_Position, mapPosition );
|
|
|
|
Vector newMapPosition = mapPosition;
|
|
newMapPosition -= m_RadarViewpointMap;
|
|
|
|
float dist = newMapPosition.LengthSqr();
|
|
if ( dist >= RADARRADIUS*RADARRADIUS && m_bRound )
|
|
{
|
|
pPackage->SetIsOffMap( true );
|
|
newMapPosition *= sqrt( RADARRADIUS*RADARRADIUS/dist );
|
|
mapPosition = m_RadarViewpointMap;
|
|
mapPosition += newMapPosition;
|
|
mapAngle = 180.0f*atan2( newMapPosition.y, newMapPosition.x )/3.141592f + 90;
|
|
}
|
|
else
|
|
{
|
|
pPackage->SetIsOffMap( false );
|
|
if ( pPackage->m_bIsDead || !pPackage->m_bIsSpotted || (pPackage->m_nAboveOrBelow != R_SAMELEVEL) || (pPackage->m_iPlayerType == PI_ENEMY && !pPackage->m_bIsSelected) )
|
|
{
|
|
mapAngle = -m_RadarRotation;
|
|
}
|
|
else
|
|
{
|
|
mapAngle = -pPackage->m_Angle[YAW]+90;
|
|
}
|
|
|
|
}
|
|
|
|
double scale = 100;
|
|
|
|
float fIconScale = cl_radar_scale.GetFloat();
|
|
|
|
fIconScale = RemapValClamped( fIconScale,
|
|
0, 1,
|
|
cl_radar_icon_scale_min.GetFloat() , 1 );
|
|
|
|
scale *= fIconScale;
|
|
|
|
static bool s_bResetTransform = false;
|
|
if ( cl_radar_fast_transforms.GetBool() )
|
|
{
|
|
RadarToHud( mapPosition, pPackage->m_HudPosition );
|
|
if ( pPackage->m_IconPackageRotate )
|
|
{
|
|
bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
|
|
pPackage->m_HudRotation = bRotate ? ( m_RadarRotation + mapAngle ) : mapAngle;
|
|
}
|
|
else
|
|
{
|
|
pPackage->m_HudRotation = 0.0f;
|
|
}
|
|
pPackage->m_HudScale = scale;
|
|
|
|
if ( s_bResetTransform )
|
|
{
|
|
ScaleformDisplayInfo displayInfo;
|
|
displayInfo.SetXScale( 100.0f );
|
|
displayInfo.SetYScale( 100.0f );
|
|
displayInfo.SetX( 0.0f );
|
|
displayInfo.SetY( 0.0f );
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackage, &displayInfo );
|
|
|
|
if ( pPackage->m_IconPackageRotate )
|
|
{
|
|
ScaleformDisplayInfo rotatedDisplayInfo;
|
|
rotatedDisplayInfo.SetRotation( 0.0f );
|
|
m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackageRotate, &rotatedDisplayInfo );
|
|
}
|
|
|
|
s_bResetTransform = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ScaleformDisplayInfo displayInfo;
|
|
|
|
displayInfo.SetXScale( scale );
|
|
displayInfo.SetYScale( scale );
|
|
|
|
displayInfo.SetX( mapPosition.x );
|
|
displayInfo.SetY( mapPosition.y );
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackage, &displayInfo );
|
|
|
|
if ( pPackage->m_IconPackageRotate )
|
|
{
|
|
ScaleformDisplayInfo rotatedDisplayInfo;
|
|
rotatedDisplayInfo.SetRotation( mapAngle );
|
|
m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackageRotate, &rotatedDisplayInfo );
|
|
}
|
|
s_bResetTransform = true;
|
|
}
|
|
|
|
pPackage->SetupIconsFromStates();
|
|
}
|
|
|
|
void SFHudRadar::PlaceHostages( void )
|
|
{
|
|
if ( !m_bFlashReady )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( !CSGameRules()->IsHostageRescueMap() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
if ( !pCSPR )
|
|
{
|
|
return;
|
|
}
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if( pLocalPlayer == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int iNumLiveHostages = 0;
|
|
int iNumDeadHostages = 0;
|
|
int iNumMovingHostages = 0;
|
|
int iNumRescuedHostages = 0;
|
|
|
|
|
|
/* // Commented out because we want to show hostages on radar to Ts
|
|
bool bIsTerrorist = ( pLocalPlayer->GetTeamNumber() == TEAM_TERRORIST );
|
|
|
|
if ( bIsTerrorist )
|
|
{
|
|
// Taking over a bot after switching to the terrorist team results in
|
|
// the hostage indicators remaining visible, so we need to remove them.
|
|
for ( int i = 0; i <= m_iLastHostageIndex; i++ )
|
|
{
|
|
if ( GetRadarHostage( i )->m_bIsActive )
|
|
RemoveHostage( i );
|
|
}
|
|
|
|
// we also want to show the number of hostages that are still alive
|
|
// and unrescued
|
|
for( int i=0; i < MAX_HOSTAGES; i++ )
|
|
{
|
|
if( pCSPR->IsHostageAlive( i ) )
|
|
iNumLiveHostages++;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
// T's can now always see basic hostage info (alive, dead) but not moving or rescued status
|
|
/*
|
|
bool bCanShowHostages = m_bShowAll || ( pLocalPlayer->GetTeamNumber() == TEAM_CT );
|
|
|
|
if ( !bCanShowHostages )
|
|
{
|
|
return;
|
|
}
|
|
*/
|
|
|
|
// Update hostage status
|
|
for( int i=0; i < MAX_HOSTAGES; i++ )
|
|
{
|
|
int nEntityID = pCSPR->GetHostageEntityID( i );
|
|
|
|
if ( nEntityID > 0 )
|
|
{
|
|
SFHudRadarIconPackage* pHostage = NULL;
|
|
|
|
int nHostageIndex = GetHostageIndexFromHostageEntityID( nEntityID );
|
|
|
|
|
|
if ( nHostageIndex == INVALID_INDEX )
|
|
{
|
|
// Create the hostage in next available slot
|
|
for ( nHostageIndex = 0; nHostageIndex < MAX_HOSTAGES; nHostageIndex++ )
|
|
{
|
|
if ( !m_Hostages[nHostageIndex].m_bIsActive )
|
|
{
|
|
pHostage = CreateHostage( nHostageIndex );
|
|
pHostage->SetPlayerTeam( TEAM_UNASSIGNED );
|
|
pHostage->m_iEntityID = nEntityID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pHostage = GetRadarHostage( nHostageIndex );
|
|
}
|
|
|
|
|
|
if ( pHostage )
|
|
{
|
|
if( pCSPR->IsHostageAlive( i ) )
|
|
{
|
|
if ( !pHostage->m_bIsActive )
|
|
{
|
|
|
|
}
|
|
|
|
pHostage->SetIsDead( false );
|
|
|
|
if ( pCSPR->IsHostageFollowingSomeone( i ) )
|
|
{
|
|
iNumMovingHostages++;
|
|
pHostage->SetIsMovingHostage( true );
|
|
|
|
if ( !pHostage->m_bHostageIsUsed )
|
|
pHostage->m_bHostageIsUsed = true;
|
|
}
|
|
else
|
|
{
|
|
iNumLiveHostages++;
|
|
pHostage->SetIsMovingHostage( false );
|
|
}
|
|
}
|
|
else if ( i <= m_iLastHostageIndex && pHostage->m_bIsActive )
|
|
{
|
|
if ( pHostage->m_bIsRescued )
|
|
{
|
|
iNumRescuedHostages++;
|
|
}
|
|
else
|
|
{
|
|
iNumDeadHostages++;
|
|
}
|
|
|
|
pHostage->SetIsDead( true );
|
|
pHostage->SetIsMovingHostage( false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update hostage positions
|
|
for( int i = 0; i < MAX_HOSTAGES; i++ )
|
|
{
|
|
SFHudRadarIconPackage* pHostage = GetRadarHostage( i );
|
|
|
|
if ( pHostage->m_bIsActive )
|
|
{
|
|
C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( pHostage->m_iEntityID );
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
// note: !pHostage->m_bHostageIsUsed : T's can always see Hostages until they get +used by CTs
|
|
bool bSpotted = ( !pHostage->m_bHostageIsUsed ||
|
|
pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT ||
|
|
( pEntity && pEntity->IsSpotted() ) ||
|
|
m_EntitySpotted.Get( pHostage->m_iEntityID ) ||
|
|
m_bShowAll );
|
|
|
|
pHostage->SetIsSpotted( bSpotted );
|
|
|
|
int nIsAboveOrBelow = R_SAMELEVEL;
|
|
C_CSPlayer *pLocalOrObserver = NULL;
|
|
if ( pLocalPlayer )
|
|
{
|
|
C_BaseEntity *target = pLocalPlayer->GetObserverTarget();
|
|
if( target && target->IsPlayer() )
|
|
pLocalOrObserver = ToCSPlayer( target );
|
|
else
|
|
pLocalOrObserver = pLocalPlayer;
|
|
}
|
|
|
|
if ( pLocalOrObserver )
|
|
{
|
|
if ( pHostage->m_Position.z > pLocalOrObserver->GetAbsOrigin().z + ABOVE_BELOW_HEIGHT )
|
|
nIsAboveOrBelow = R_ABOVE;
|
|
else if ( pHostage->m_Position.z < pLocalOrObserver->GetAbsOrigin().z - ABOVE_BELOW_HEIGHT )
|
|
nIsAboveOrBelow = R_BELOW;
|
|
}
|
|
|
|
pHostage->SetIsAboveOrBelow( nIsAboveOrBelow );
|
|
|
|
SetIconPackagePosition( pHostage );
|
|
|
|
bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
|
|
// hostage always faces the same way
|
|
if ( !bRotate )
|
|
pHostage->m_Angle = QAngle( 0, 90, 0 );
|
|
else
|
|
{
|
|
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
|
pHostage->m_Angle = MainViewAngles( nSlot );
|
|
}
|
|
|
|
if ( pEntity && !pEntity->IsDormant() && bSpotted )
|
|
{
|
|
Assert( dynamic_cast<CHostage*>( pEntity ) );
|
|
pHostage->m_Position = pEntity->GetNetworkOrigin();
|
|
}
|
|
}
|
|
}
|
|
|
|
int hostageIndex = 0;
|
|
|
|
for ( int i = 0; i < iNumDeadHostages; i++ )
|
|
{
|
|
m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_DEAD );
|
|
}
|
|
|
|
for ( int i = 0; i < iNumRescuedHostages; i++ )
|
|
{
|
|
m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_RESCUED );
|
|
}
|
|
|
|
for ( int i = 0; i < iNumMovingHostages; i++ )
|
|
{
|
|
m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_TRANSIT );
|
|
}
|
|
|
|
for ( int i = 0; i < iNumLiveHostages; i++ )
|
|
{
|
|
m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_ALIVE );
|
|
}
|
|
|
|
for ( ; hostageIndex < MAX_HOSTAGES && m_HostageStatusIcons[hostageIndex].m_IconPackage != NULL; hostageIndex++ )
|
|
{
|
|
m_HostageStatusIcons[hostageIndex].SetStatus( SFHudRadarHostageIcons::HI_UNUSED );
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::UpdateAllDefusers( void )
|
|
{
|
|
if ( !m_bTrackDefusers )
|
|
{
|
|
return;
|
|
}
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if( pLocalPlayer == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
|
|
{
|
|
SFHudRadarIconPackage * pPackage = GetRadarDefuser( i );
|
|
|
|
if ( pPackage && pPackage->m_bIsActive )
|
|
{
|
|
C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( pPackage->m_iEntityID );
|
|
|
|
bool bSpotted = ( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT || ( pEntity && pEntity->IsSpotted() ) || m_EntitySpotted.Get( pPackage->m_iEntityID ) );
|
|
|
|
pPackage->SetIsSpotted( bSpotted );
|
|
|
|
if ( bSpotted && pEntity && !pEntity->IsDormant() )
|
|
{
|
|
SetDefuserPos( pPackage->m_iEntityID,
|
|
pEntity->GetNetworkOrigin().x,
|
|
pEntity->GetNetworkOrigin().y,
|
|
pEntity->GetNetworkOrigin().z,
|
|
pEntity->GetNetworkAngles().y );
|
|
}
|
|
}
|
|
|
|
// update radar position and visibility
|
|
if ( pPackage && pPackage->m_bIsActive )
|
|
{
|
|
SetIconPackagePosition( pPackage );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SFHudRadar::PlacePlayers( void )
|
|
{
|
|
if ( !m_bFlashReady )
|
|
{
|
|
return;
|
|
}
|
|
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
if ( !pCSPR )
|
|
{
|
|
return;
|
|
}
|
|
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if( pLocalPlayer == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int localPlayerIndex = pLocalPlayer->entindex()-1;
|
|
if ( localPlayerIndex == INVALID_INDEX )
|
|
return;
|
|
|
|
int localTeamNumber = pLocalPlayer->GetAssociatedTeamNumber();
|
|
|
|
SFHudRadarIconPackage* pwalk = m_Players;
|
|
int playerIndex;
|
|
|
|
for ( int i = 0; i <= m_iLastPlayerIndex; i++, pwalk++ )
|
|
{
|
|
if ( pwalk->m_IconPackage && pwalk->m_bIsActive )
|
|
{
|
|
playerIndex = i+1;
|
|
|
|
C_CSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( playerIndex ) );
|
|
|
|
bool playerIsActive = pPlayer != NULL && !pPlayer->IsDormant();
|
|
int nIsAboveOrBelow = R_SAMELEVEL;
|
|
|
|
// we do all the pCSPR stuff because the player may not have been given
|
|
// to us by the server yet. If that's the case, we can't use the player
|
|
// pointer to find anything out, we have to use the PCSPR which keeps some
|
|
// of this data ( like team numbers, spotted, hasC4 etc. The dormant means
|
|
// that it's not in our view
|
|
|
|
if ( pPlayer && pCSPR->IsConnected( playerIndex ) )
|
|
{
|
|
pwalk->SetIsBot( pCSPR->IsFakePlayer( playerIndex ) );
|
|
|
|
pwalk->m_Health = pCSPR->GetHealth( playerIndex );
|
|
|
|
if ( !pCSPR->IsAlive( playerIndex ) )
|
|
{
|
|
pwalk->m_Health = 0;
|
|
if( pCSPR->GetControlledByPlayer( playerIndex ) )
|
|
{
|
|
pwalk->SetIsControlledBot();
|
|
}
|
|
else
|
|
{
|
|
pwalk->SetIsDead( true );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pwalk->SetIsDead( false );
|
|
|
|
//it's hard to figure out if this player has been spotted, and if spotted has enough info to be
|
|
//shown.
|
|
|
|
bool bSameTeam = ( localTeamNumber == pCSPR->GetTeam( playerIndex ) );
|
|
bool bIsEnemy = pPlayer->IsOtherEnemy( pLocalPlayer ) && localPlayerIndex != playerIndex;
|
|
|
|
bool bHasValidPosition = playerIsActive || ( pwalk->m_Position.x != 0 || pwalk->m_Position.y != 0 );
|
|
|
|
bool bPlayerSpotted = ( m_EntitySpotted.Get( playerIndex ) || ( playerIsActive && pPlayer->IsSpotted() ) );
|
|
bool bSpottedByFriends = !bIsEnemy;
|
|
|
|
// verify here on the client that we do in fact see the entity how the player would expect to see the entity
|
|
// if the local player is in smoke or if they are looking through smoke, we double check if they can see them on radar
|
|
// use the networked position and not the stored position because the stored one is stale
|
|
Vector vecOtherPos( pPlayer->GetNetworkOrigin( ).x, pPlayer->GetNetworkOrigin( ).y, ( pPlayer->GetNetworkOrigin( ).z + 56 ) );
|
|
if ( bIsEnemy && bPlayerSpotted )
|
|
{
|
|
bSpottedByFriends = pPlayer->IsSpottedByFriends( localPlayerIndex );
|
|
|
|
float flDist = ( pLocalPlayer->EyePosition( ) - vecOtherPos ).Length2D( );
|
|
if ( flDist < 1600 && bSpottedByFriends == false &&
|
|
LineGoesThroughSmoke( pLocalPlayer->EyePosition(), vecOtherPos, 1.0f ) )
|
|
{
|
|
bPlayerSpotted = false;
|
|
}
|
|
}
|
|
|
|
if ( bHasValidPosition && ( (bSameTeam && !bIsEnemy) || m_bShowAll || bPlayerSpotted ) )
|
|
{
|
|
bool bSpottedByLocalPlayer = bSameTeam ? true : pPlayer->IsSpottedBy( localPlayerIndex );
|
|
pwalk->SetIsSpotted( true );
|
|
pwalk->SetIsSpottedByFriendsOnly( (bSpottedByFriends && !bSpottedByLocalPlayer) );
|
|
|
|
if ( playerIsActive && pPlayer->HasDefuser() )
|
|
{
|
|
// attach a defuser icon to this player if one does not already exist
|
|
if ( GetDefuseIndexFromEntityID( playerIndex ) == INVALID_INDEX )
|
|
{
|
|
CreateDefuser( playerIndex );
|
|
}
|
|
}
|
|
|
|
if ( playerIsActive && pPlayer->HasC4() )
|
|
{
|
|
m_bBombIsSpotted = true;
|
|
m_BombPosition = pwalk->m_Position;
|
|
m_nBombHolderUserId = pPlayer->GetUserID();
|
|
}
|
|
|
|
// set is selected
|
|
C_CSPlayer *pLocalOrObserver = ToCSPlayer( pLocalPlayer->GetObserverTarget() );
|
|
pwalk->SetIsSelected( pLocalOrObserver && pPlayer == pLocalOrObserver );
|
|
}
|
|
else
|
|
{
|
|
pwalk->SetIsSpotted( false );
|
|
}
|
|
}
|
|
|
|
pwalk->SetPlayerTeam( pCSPR->GetTeam( playerIndex ) );
|
|
pwalk->SetIsOnLocalTeam( localTeamNumber == pCSPR->GetTeam( playerIndex ) );
|
|
|
|
pwalk->SetIsPlayer( i == localPlayerIndex );
|
|
pwalk->SetIsSpeaking( GetClientVoiceMgr()->IsPlayerSpeaking( playerIndex ) && GetClientVoiceMgr()->IsPlayerAudible( playerIndex ) );
|
|
|
|
UpdatePlayerNumber( pwalk );
|
|
|
|
C_CSPlayer *pLocalOrObserver = NULL;
|
|
if ( pLocalPlayer )
|
|
{
|
|
C_BaseEntity *target = pLocalPlayer->GetObserverTarget();
|
|
if( target && target->IsPlayer() )
|
|
pLocalOrObserver = ToCSPlayer( target );
|
|
else
|
|
pLocalOrObserver = pLocalPlayer;
|
|
}
|
|
|
|
if ( pLocalOrObserver )
|
|
{
|
|
if ( pwalk->m_Position.z > pLocalOrObserver->GetAbsOrigin().z + ABOVE_BELOW_HEIGHT )
|
|
nIsAboveOrBelow = R_ABOVE;
|
|
else if ( pwalk->m_Position.z < pLocalOrObserver->GetAbsOrigin().z - ABOVE_BELOW_HEIGHT )
|
|
nIsAboveOrBelow = R_BELOW;
|
|
}
|
|
|
|
pwalk->SetIsAboveOrBelow( nIsAboveOrBelow );
|
|
|
|
}
|
|
else
|
|
{
|
|
pwalk->SetIsSpotted( false );
|
|
pwalk->SetIsSpeaking( false );
|
|
}
|
|
|
|
if ( playerIsActive && pwalk->m_bIsSpotted )
|
|
{
|
|
// when the local player dies the system reports the local players position
|
|
// as the position of the spectator camera. If we let that happen, the player's
|
|
// X migrates from the point they died to follow the camera. Can't have that,
|
|
// so avoid setting the position if we're dead and in observer mode
|
|
|
|
if ( m_iObserverMode == OBS_MODE_NONE || i != localPlayerIndex )
|
|
{
|
|
// dkorus and pfreese: Changed from local origin and local angles to last networked version to address jitter issues for pax demo 2011
|
|
if ( !pwalk->m_bIsDead )
|
|
pwalk->m_Position = pPlayer->GetNetworkOrigin();
|
|
|
|
// only set the angle of the icon if the player isn't above or below us
|
|
if ( nIsAboveOrBelow != R_SAMELEVEL || pwalk->IsHostageType( ) || ( pwalk->m_iPlayerType == PI_ENEMY && !pwalk->m_bIsSelected ) )
|
|
{
|
|
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
|
pwalk->m_Angle = MainViewAngles( nSlot );
|
|
}
|
|
else
|
|
pwalk->m_Angle = pPlayer->EyeAngles( );
|
|
|
|
if ( pPlayer->HasC4() )
|
|
{
|
|
m_BombPosition = pwalk->m_Position;
|
|
m_nBombHolderUserId = pPlayer->GetUserID();
|
|
}
|
|
}
|
|
}
|
|
|
|
SetIconPackagePosition( pwalk );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void SFHudRadar::UpdateMiscIcons( void )
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if ( !pLocalPlayer )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// We show the entire dashboard in spectator mode now, so you can see bomb/hostage status, etc.
|
|
m_bShowingDashboard = true;
|
|
|
|
// Uncomment this line to disable the radar dashboard in spectator mode:
|
|
// m_bShowingDashboard = ( pLocalPlayer->GetObserverMode() == OBS_MODE_NONE );
|
|
|
|
const char *pszLocation = pLocalPlayer->GetLastKnownPlaceName();
|
|
|
|
if ( pszLocation )
|
|
{
|
|
SetLocationText( g_pVGuiLocalize->Find( pszLocation ) );
|
|
}
|
|
else
|
|
{
|
|
SetLocationText( NULL );
|
|
}
|
|
|
|
|
|
|
|
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
|
|
if ( !pCSPR )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// show the bomb under the radar if the player has this set
|
|
static ConVarRef cl_hud_bomb_under_radar( "cl_hud_bomb_under_radar" );
|
|
bool bShowBombUnderRadar = ( cl_hud_bomb_under_radar.GetInt( ) == 1 && pLocalPlayer->HasC4() );
|
|
WITH_SFVALUEARRAY( args, 1 )
|
|
{
|
|
g_pScaleformUI->ValueArray_SetElement( args, 0, bShowBombUnderRadar );
|
|
g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ShowC4", args, 1 );
|
|
}
|
|
|
|
m_fBombAlpha = 0.0f;
|
|
m_fDefuserAlpha = 0.0f;
|
|
|
|
if ( CSGameRules()->IsBombDefuseMap() )
|
|
{
|
|
if ( m_bBombPlanted )
|
|
{
|
|
FOR_EACH_VEC( g_PlantedC4s, iBomb )
|
|
{
|
|
C_PlantedC4 * pC4 = g_PlantedC4s[iBomb];
|
|
if ( pC4 && pC4->IsBombActive() )
|
|
{
|
|
bool bLocalPlayerCanSeeBomb =( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || m_bShowAll || ( pC4 && !pC4->IsDormant() && pC4->IsSpotted() ) );
|
|
if ( bLocalPlayerCanSeeBomb && pC4 && !pC4->IsDormant() )
|
|
{
|
|
m_bBombIsSpotted = true;
|
|
m_BombPosition = pC4->GetNetworkOrigin();
|
|
m_nBombHolderUserId = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( m_nBombEntIndex != -1 && ( !m_bBombIsSpotted || m_bBombDropped ) )
|
|
{
|
|
C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( m_nBombEntIndex );
|
|
|
|
bool bLocalPlayerCanSeeBomb =( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || m_bShowAll || ( pEntity && !pEntity->IsDormant() && pEntity->IsSpotted() ) );
|
|
if ( bLocalPlayerCanSeeBomb && pEntity && !pEntity->IsDormant() )
|
|
{
|
|
Assert( pEntity && FClassnameIs( pEntity, "weapon_c4" ) );
|
|
m_bBombIsSpotted = true;
|
|
m_BombPosition = pEntity->GetNetworkOrigin();
|
|
m_nBombHolderUserId = -1;
|
|
}
|
|
}
|
|
|
|
float now = gpGlobals->curtime;
|
|
bool drawBomb = false;
|
|
|
|
bool bBombPositionIsValid = ( m_BombPosition.x != 0 || m_BombPosition.y != 0 );
|
|
|
|
if ( CSGameRules() && CSGameRules()->IsPlayingCoopMission() )
|
|
{
|
|
drawBomb = false;
|
|
}
|
|
else if ( bBombPositionIsValid && !m_bBombExploded && m_bBombIsSpotted )
|
|
{
|
|
drawBomb = true;
|
|
m_fBombSeenTime = now;
|
|
m_fBombAlpha = 1.0f;
|
|
}
|
|
else if ( m_bBombExploded )
|
|
{
|
|
m_fBombAlpha = 0;
|
|
m_fBombSeenTime = TIMER_INIT;
|
|
}
|
|
else
|
|
{
|
|
m_fBombAlpha = clamp( 1.0f - ( now - m_fBombSeenTime )/BOMB_FADE_TIME, 0.0f, 1.0f );
|
|
if ( m_fBombAlpha > 0 )
|
|
{
|
|
drawBomb = true;
|
|
}
|
|
else
|
|
{
|
|
m_fBombSeenTime = TIMER_INIT;
|
|
}
|
|
}
|
|
|
|
if ( drawBomb )
|
|
{
|
|
m_bShowBombHighlight = !m_bBombDefused && ( m_bBombPlanted || m_bBombDropped );
|
|
}
|
|
}
|
|
else if ( CSGameRules()->IsHostageRescueMap() )
|
|
{
|
|
m_bShowingHostageZone = pLocalPlayer->IsInHostageRescueZone();
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ShowHostages", NULL, 0 );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudRadar::ApplySpectatorModes( void )
|
|
{
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
if ( !pLocalPlayer )
|
|
return;
|
|
|
|
m_bShowAll = false;
|
|
m_iObserverMode = pLocalPlayer->GetObserverMode();
|
|
|
|
if ( engine->IsHLTV() || pLocalPlayer->IsSpectator() )
|
|
{
|
|
m_bShowAll = true;
|
|
}
|
|
else if ( m_iObserverMode != OBS_MODE_NONE ) // is not a live player
|
|
{
|
|
// respect mp_forcecamera
|
|
static ConVarRef mp_forcecamera( "mp_forcecamera" );
|
|
m_bShowAll = ( mp_forcecamera.GetInt() == OBS_ALLOW_ALL );
|
|
}
|
|
|
|
// mp_radar_showall trumps all
|
|
static ConVarRef mp_radar_showall( "mp_radar_showall" );
|
|
if ( mp_radar_showall.GetInt() && (
|
|
( pLocalPlayer->GetAssociatedTeamNumber() == mp_radar_showall.GetInt() ) ||
|
|
( mp_radar_showall.GetInt() == 1 )
|
|
) )
|
|
{
|
|
m_bShowAll = true;
|
|
}
|
|
|
|
// Radar type
|
|
bool bRoundRadar = true;
|
|
IViewPortPanel* panel = GetViewPortInterface()->FindPanelByName( PANEL_SCOREBOARD );
|
|
if ( engine->IsHLTV() || pLocalPlayer->IsSpectator() || (panel->IsVisible() && cl_radar_square_with_scoreboard.GetBool()) )
|
|
bRoundRadar = false;
|
|
else if ( pLocalPlayer->IsAlive() == false &&
|
|
(m_iObserverMode == OBS_MODE_FIXED ||
|
|
m_iObserverMode == OBS_MODE_CHASE ||
|
|
m_iObserverMode == OBS_MODE_ROAMING ||
|
|
m_iObserverMode == OBS_MODE_IN_EYE) )
|
|
{
|
|
bRoundRadar = false;
|
|
}
|
|
SwitchRadarToRound( bRoundRadar );
|
|
}
|
|
|
|
void SFHudRadar::UpdateDecoys( void )
|
|
{
|
|
for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
|
|
{
|
|
SFHudRadarIconPackage* pPackage = GetRadarDecoy( i );
|
|
|
|
if ( pPackage && pPackage->m_bIsActive )
|
|
{
|
|
SetIconPackagePosition( pPackage );
|
|
if ( !pPackage->IsVisible() )
|
|
{
|
|
RemoveDecoy( i );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::ResizeHud( void )
|
|
{
|
|
if ( !m_pScaleformUI )
|
|
return;
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ForceResizeHud", NULL, 0 );
|
|
}
|
|
}
|
|
|
|
void SFHudRadar::ProcessInput( void )
|
|
{
|
|
LazyCreateGoalIcons();
|
|
|
|
LazyCreatePlayerIcons();
|
|
|
|
ApplySpectatorModes();
|
|
|
|
PositionRadarViewpoint();
|
|
|
|
PlaceGoalIcons();
|
|
|
|
PlacePlayers();
|
|
|
|
PlaceHostages();
|
|
|
|
UpdateDecoys();
|
|
|
|
UpdateAllDefusers();
|
|
|
|
UpdateMiscIcons();
|
|
|
|
SetupIconsFromStates();
|
|
}
|
|
|
|
void SFHudRadar::SwitchRadarToRound( bool toRound )
|
|
{
|
|
if ( !m_bActive || !m_bFlashReady )
|
|
return;
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
if ( m_MapRotation )
|
|
{
|
|
SafeReleaseSFVALUE( m_MapRotation );
|
|
}
|
|
if ( m_MapTranslation )
|
|
{
|
|
SafeReleaseSFVALUE( m_MapTranslation );
|
|
}
|
|
|
|
if ( toRound )
|
|
{
|
|
m_bRound = true;
|
|
|
|
m_MapRotation = m_pScaleformUI->Value_GetMember( m_Radar, "MapRotation" );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SwitchRadarToRound", NULL, 0 );
|
|
}
|
|
else
|
|
{
|
|
m_bRound = false;
|
|
|
|
m_MapRotation = m_pScaleformUI->Value_GetMember( m_Radar, "MapRotationSq" );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SwitchRadarToSquare", NULL, 0 );
|
|
}
|
|
|
|
if ( m_MapRotation )
|
|
{
|
|
m_MapTranslation = m_pScaleformUI->Value_GetMember( m_MapRotation, "MapTranslation" );
|
|
}
|
|
}
|
|
}
|
|
|