Counter Strike : Global Offensive Source Code
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.
 
 
 
 
 
 

3608 lines
84 KiB

// ========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// =============================================================================//
#include "cbase.h"
#include "hudelement.h"
#include "mapoverview.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 "HUD/sfhudfreezepanel.h"
#include "HUD/sfhudwinpanel.h"
#include "HUD/sfhud_teamcounter.h"
#include "c_plantedc4.h"
#include "c_world.h"
#include "gametypes.h"
#include "hltvreplaysystem.h"
#include "clientmode_shared.h"
//memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static const float NOTSPOTTEDRADIUS = 1400.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 INVALID_INDEX = -1;
ConVar mapoverview_allow_client_draw( "mapoverview_allow_client_draw", "0", FCVAR_RELEASE, "Allow a client to draw on the map overview" );
ConVar mapoverview_allow_grid_usage( "mapoverview_allow_grid_usage", "0", FCVAR_RELEASE, "When set to 1, allows turning on the (experimental) grid for drawing." );
ConVar mapoverview_icon_scale( "mapoverview_icon_scale", "1.0", FCVAR_RELEASE | FCVAR_ARCHIVE, "Sets the icon scale multiplier for the overview map. Valid values are 0.5 to 3.0.", true, 0.5f, true, 3.0f );
/*******************************************************************************
* data definitions
*/
static const char* playerIconNames[] = {
"Greande_HE",
"Greande_FLASH",
"Greande_SMOKE",
"Greande_MOLOTOV",
"Greande_DECOY",
"Defuser",
"AbovePlayer",
"BelowPlayer",
"Flashed",
"PlayerNumber",
"PlayerNameCT",
"PlayerNameT",
// below this, the icons are rotated
"PlayerIndicator",
"SpeakingOnMap",
"HostageTransitOnMap",
"CTOnMap",
"CTDeath",
"CTGhost",
"TOnMap",
"TDeath",
"TGhost",
"EnemyOnMap",
"EnemyDeath",
"EnemyGhost",
"HostageOnMap",
"HostageDeath",
"HostageGhost",
"DirectionalIndicator",
"MuzzleFlash",
"LowHealth",
"Selected",
NULL
};
static const char* hostageIconNames[] = {
"HostageDead",
"HostageRescued",
"HostageAlive",
"HostageTransit",
NULL
};
static const char* overviewIconNames[] = {
"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",
"hegrenade_detonate",
"flashbang_detonate",
"smokegrenade_detonate",
"smokegrenade_expired",
"inferno_startburn",
"inferno_expire",
"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,
HE_DETONATE,
FLASH_DETONATE,
SMOKE_DETONATE,
SMOKE_EXPIRE,
MOLOTOV_DETONATE,
MOLOTOV_EXPIRE,
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> SFMapOverview::m_messageMap( maplessfunc );
DECLARE_HUDELEMENT( SFMapOverview );
DECLARE_HUD_MESSAGE( SFMapOverview, ProcessSpottedEntityUpdate );
SFUI_BEGIN_GAME_API_DEF
SFUI_DECL_METHOD( MapLoaded ),
SFUI_DECL_METHOD( ToggleOverviewMap ),
SFUI_DECL_METHOD( AllowMapDrawing ),
SFUI_DECL_METHOD( GetWorldDistance ),
//SFUI_DECL_METHOD( GetNavPath ),
SFUI_END_GAME_API_DEF( SFMapOverview, MapOverview );
CON_COMMAND( drawoverviewmap, "Draws the overview map" )
{
( GET_HUDELEMENT( SFMapOverview ) )->ShowMapOverview( true );
}
CON_COMMAND( hideoverviewmap, "Hides the overview map" )
{
( GET_HUDELEMENT( SFMapOverview ) )->ShowMapOverview( false );
}
/**********************************************************************
* SFMapOverviewIconPackage code
*/
SFMapOverview::SFMapOverviewIconPackage::SFMapOverviewIconPackage()
{
ClearAll();
}
SFMapOverview::SFMapOverviewIconPackage::~SFMapOverviewIconPackage()
{
}
void SFMapOverview::SFMapOverviewIconPackage::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_bIsLowHealth = false;
m_bIsSelected = false;
m_bIsFlashed = false;
m_bIsFiring = false;
m_bIsSpotted = false;
m_fGhostTime = 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_nGrenadeType = -1;
m_bIsDefuser = false;
}
void SFMapOverview::SFMapOverviewIconPackage::Init( IScaleformUI* pui, SFVALUE iconPackage )
{
m_pScaleformUI = pui;
m_IconPackage = pui->CreateValue( iconPackage );
m_IconPackageRotate = m_pScaleformUI->Value_GetMember( iconPackage, "RotatedLayer" );
for ( uint64 i = 0; i < PI_NUM_ICONS && playerIconNames[i] != NULL; i++ )
{
if ( i < PI_FIRST_ROTATED )
{
m_Icons[i] = pui->Value_GetMember( m_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 & ( 1ll << i ) ) != 0 );
}
}
ScaleformDisplayInfo displayInfo;
displayInfo.SetAlpha( m_fCurrentAlpha * 100.0f );
displayInfo.SetVisibility( m_iCurrentVisibilityFlags != 0 );
m_pScaleformUI->Value_SetDisplayInfo( m_IconPackage, &displayInfo );
}
void SFMapOverview::SFMapOverviewIconPackage::NukeFromOrbit( SFMapOverview* pSFUI )
{
if ( pSFUI->FlashAPIIsValid() )
{
pSFUI->SafeReleaseSFVALUE( m_IconPackage );
pSFUI->SafeReleaseSFVALUE( m_IconPackageRotate );
for ( uint64 i = 0; i < PI_NUM_ICONS; i++ )
{
pSFUI->SafeReleaseSFVALUE( m_Icons[i] );
}
}
ClearAll();
}
void SFMapOverview::SFMapOverviewIconPackage::StartRound( void )
{
m_Health = 100;
m_bOffMap = false;
m_bIsLowHealth = false;
m_bIsSelected = false;
m_bIsFlashed = false;
m_bIsFiring = false;
m_bIsSpotted = false;
m_fGhostTime = 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_nGrenadeType = -1;
m_Position = vec3_origin;
m_Angle.Init();
SetAlpha( 0 );
SetVisibilityFlags( 0 );
}
bool SFMapOverview::SFMapOverviewIconPackage::IsVisible( void )
{
return ( m_fCurrentAlpha != 0 && m_iCurrentVisibilityFlags != 0 );
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsPlayer( bool value )
{
m_bIsPlayer = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsSpeaking ( bool value )
{
m_bIsSpeaking = value && m_bIsOnLocalTeam;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsOffMap( bool value )
{
m_bOffMap = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsLowHealth( bool value )
{
m_bIsLowHealth = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsSelected( bool value )
{
m_bIsSelected = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsFlashed( bool value )
{
m_bIsFlashed = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsFiring( bool value )
{
m_bIsFiring = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsAboveOrBelow( int value )
{
m_nAboveOrBelow = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsMovingHostage( bool value )
{
m_bIsMovingHostage = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsRescued( bool value )
{
m_bIsRescued = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsOnLocalTeam( bool value )
{
m_bIsOnLocalTeam = value;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsControlledBot( void )
{
m_bIsDead = true;
m_bIsSpotted = true;
m_fDeadTime = TIMER_INIT;
m_fGhostTime = TIMER_INIT;
}
void SFMapOverview::SFMapOverviewIconPackage::SetIsDead( bool value )
{
if ( value != m_bIsDead )
{
if ( value )
{
// SetIsSpotted( true );
m_fDeadTime = gpGlobals->curtime;
}
else
{
m_fDeadTime = TIMER_INIT;
}
m_bIsDead = value;
}
}
void SFMapOverview::SFMapOverviewIconPackage::SetGrenadeExpireTime( float value )
{
if ( value )
{
m_fGrenExpireTime = value;
}
}
void SFMapOverview::SFMapOverviewIconPackage::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 SFMapOverview::SFMapOverviewIconPackage::SetPlayerTeam( int team )
{
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
if( pLocalPlayer == NULL )
{
return;
}
int newType;
switch( team )
{
case TEAM_UNASSIGNED:
newType = PI_HOSTAGE;
break;
case TEAM_TERRORIST:
newType = pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || pLocalPlayer->IsObserver() ? PI_T : PI_ENEMY;
break;
case TEAM_CT:
newType =pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT || pLocalPlayer->IsObserver() ? PI_CT : PI_ENEMY;
break;
case TEAM_SPECTATOR:
default:
newType = 0;
break;
}
if ( m_iPlayerType != newType )
{
m_iPlayerType = newType;
SetVisibilityFlags( 0 );
}
}
void SFMapOverview::SFMapOverviewIconPackage::SetupIconsFromStates( void )
{
uint64 flags = 0;
float alpha = 1;
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
if( pLocalPlayer == NULL )
return;
bool bShowAll = false;
if ( pLocalPlayer->IsSpectator() || g_bEngineIsHLTV )
bShowAll = true;
if ( m_iPlayerType != 0 )
{
flags = 1ll << m_iPlayerType;
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 <<= 1;
}
}
}
}
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 );
// shifting to show the "ghost" icon
flags <<= 2;
}
}
else
{
if ( m_bIsMovingHostage )
{
flags |= 1 << PI_HOSTAGE_MOVING;
}
if ( m_bIsSpeaking )
{
flags |= 1 << PI_SPEAKING;
}
if ( m_bIsLowHealth )
{
flags |= 1 << PI_LOWHEALTH;
}
if ( m_bIsSelected )
{
flags |= 1 << PI_SELECTED;
}
if ( m_bIsFlashed )
{
flags |= 1 << PI_FLASHED;
}
if ( m_bIsFiring )
{
flags |= 1 << PI_MUZZLE_FLASH;
}
bool bSameTeamOrSpec = false;
if ( m_iPlayerType == PI_CT && (pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT || bShowAll) )
{
flags |= 1 << PI_PLAYER_NAME_CT;
bSameTeamOrSpec = true;
}
if ( m_iPlayerType == PI_T && (pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || bShowAll) )
{
flags |= 1 << PI_PLAYER_NAME_T;
bSameTeamOrSpec = true;
}
if ( bSameTeamOrSpec )
flags |= 1 << PI_PLAYER_NUMBER;
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 );
}
}
}
}
else if ( m_nGrenadeType > -1 )
{
flags = 1ll << m_nGrenadeType;
float flFadeTime = 1.0f;
float deadElapsedTime = (m_fGrenExpireTime <= 0 ) ? 0 : gpGlobals->curtime - m_fGrenExpireTime;
if ( deadElapsedTime > flFadeTime )
{
m_fGrenExpireTime = TIMER_INIT;
flags = 0;
}
else
{
alpha = clamp( 1.0f - deadElapsedTime / flFadeTime, 0.0f, 1.0f );
}
}
//GetPlayerSlotIndex( m_iEntityID/*engine->GetPlayerForUserID( m_iEntityID )*/ );
SetAlpha( alpha );
SetVisibilityFlags( flags );
}
void SFMapOverview::SFMapOverviewIconPackage::SetVisibilityFlags( uint64 newFlags )
{
newFlags &= ( ( 1ll << PI_NUM_ICONS )-1 );
uint64 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 ( uint64 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 & ( 1ll << i ) ) != 0 );
}
}
}
}
m_iCurrentVisibilityFlags = newFlags;
}
}
void SFMapOverview::SFMapOverviewIconPackage::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 SFMapOverview::SFMapOverviewIconPackage::SetIsDefuse( bool bValue )
{
m_bIsDefuser = bValue;
}
void SFMapOverview::SFMapOverviewIconPackage::SetGrenadeType( int nValue )
{
m_nGrenadeType = nValue;
}
/**********************************************************************
**********************************************************************
**********************************************************************
**********************************************************************
**********************************************************************
* SFHudHostageIcon
*/
SFMapOverview::SFMapOverviewHostageIcons::SFMapOverviewHostageIcons()
{
m_IconPackage = NULL;
V_memset( m_Icons, 0,sizeof( m_Icons ) );
m_iCurrentIcon = HI_UNUSED;
}
SFMapOverview::SFMapOverviewHostageIcons::~SFMapOverviewHostageIcons()
{
}
void SFMapOverview::SFMapOverviewHostageIcons::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 SFMapOverview::SFMapOverviewHostageIcons::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 SFMapOverview::SFMapOverviewHostageIcons::ReleaseHandles( SFMapOverview* pradar )
{
if ( m_IconPackage && pradar->FlashAPIIsValid() )
{
pradar->SafeReleaseSFVALUE( m_IconPackage );
for ( int i = 0; i < HI_NUM_ICONS; i++ )
{
pradar->SafeReleaseSFVALUE( m_Icons[i] );
}
}
}
/**********************************************************************
**********************************************************************
**********************************************************************
**********************************************************************
**********************************************************************
* SFMapOverview Code
*
*/
SFMapOverview::SFMapOverview( const char *value ) : SFHudFlashInterface( value ),
m_fMapSize( 1.0f ),
m_fMapScale( 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_iLastGrenadeIndex( 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_bShowBombHighlight( false ),
m_bShowMapOverview( false ),
m_bShowAll( false ),
m_bShowingDashboard( false ),
m_iObserverMode( OBS_MODE_NONE ),
m_bTrackDefusers( false ),
m_bVisible( false )
{
//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_AllIcons, 0, sizeof( m_AllIcons ) );
m_EntitySpotted.ClearAll();
}
SFMapOverview::~SFMapOverview()
{
}
/**************************************
* hud element functions
*/
void SFMapOverview::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( SFMapOverview, ProcessSpottedEntityUpdate );
}
void SFMapOverview::LevelInit( void )
{
if ( !m_bFlashReady && !m_bFlashLoading )
{
SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFMapOverview, this, MapOverview );
}
}
void SFMapOverview::LevelShutdown( void )
{
if ( m_bFlashReady || m_bFlashLoading )
{
RemoveFlashElement();
}
}
bool SFMapOverview::ShouldDraw( void )
{
if ( IsTakingAFreezecamScreenshot() || !m_bShowMapOverview )
return false;
return cl_drawhud.GetBool();// && CHudElement::ShouldDraw();
}
bool SFMapOverview::CanShowOverview( void )
{
CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer && (pLocalPlayer->GetObserverMode() == OBS_MODE_NONE ||
pLocalPlayer->GetObserverMode() == OBS_MODE_DEATHCAM || pLocalPlayer->GetObserverMode() == OBS_MODE_FREEZECAM ) )
{
return false;
}
if ( g_HltvReplaySystem.GetHltvReplayDelay() )
return false;
return true;
}
void SFMapOverview::SetActive( bool bActive )
{
if ( bActive == true && !CanShowOverview() )
return;
Show( bActive );
CHudElement::SetActive( bActive );
}
void SFMapOverview::Show( bool show )
{
if ( show == true && !CanShowOverview() )
return;
if ( m_bFlashReady && show != m_bActive )
{
WITH_SLOT_LOCKED
{
if ( show )
{
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;
}
}
UpdateAllPlayerNamesAndNumbers();
}
}
void SFMapOverview::ShowPanel( bool bShow )
{
if ( bShow != m_bVisible )
{
if ( bShow )
{
Show( true );
}
else
{
Show( false );
}
}
}
//
// /**********************************
// * initialization code goes here
// */
//
//
// these overload the ScaleformFlashInterfaceMixin class
void SFMapOverview::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_AllIcons[RI_DASHBOARD] = dashboard;
if ( !dashboard )
{
return;
}
char hostageIconName[20] = {"HostageStatusX"};
int index = 0;
SFVALUE hostageIcon;
do
{
hostageIconName[13] = index + '1';
hostageIcon = m_pScaleformUI->Value_GetMember( dashboard, hostageIconName );
if ( hostageIcon == NULL )
{
break;
}
else
{
m_HostageStatusIcons[index].Init( m_pScaleformUI, hostageIcon );
SafeReleaseSFVALUE( hostageIcon );
}
} while( ++index < MAX_HOSTAGES );
for ( int i = 0; overviewIconNames[i] != NULL; i++ )
{
m_AllIcons[i] = m_pScaleformUI->Value_GetMember( dashboard, overviewIconNames[i] );
}
// m_LocationText = m_pScaleformUI->TextObject_MakeTextObjectFromMember( dashboard, "Location" );
// if ( m_LocationText )
// {
// m_LocationText->SetText( m_wcLocationString );
// }
}
void SFMapOverview::FlashReady( void )
{
// these aren't ready until after the first frame, so they have to get connected here instead of in
// FlashLoaded()
m_AllIcons[RI_BOMB_ICON_PACKAGE] = m_pScaleformUI->Value_Invoke( m_IconTranslation, "createBombPack", NULL, 0 );
if ( m_AllIcons[RI_BOMB_ICON_PACKAGE] )
{
m_AllIcons[RI_BOMB_ICON_DROPPED] = m_pScaleformUI->Value_GetMember( m_AllIcons[RI_BOMB_ICON_PACKAGE], "DroppedBomb" );
m_AllIcons[RI_BOMB_ICON_PLANTED] = m_pScaleformUI->Value_GetMember( m_AllIcons[RI_BOMB_ICON_PACKAGE], "PlantedBomb" );
m_AllIcons[RI_BOMB_ICON_BOMB_CT] = m_pScaleformUI->Value_GetMember( m_AllIcons[RI_BOMB_ICON_PACKAGE], "BombCT" );
m_AllIcons[RI_BOMB_ICON_BOMB_T] = m_pScaleformUI->Value_GetMember( m_AllIcons[RI_BOMB_ICON_PACKAGE], "BombT" );
m_AllIcons[RI_BOMB_ICON_BOMB_ABOVE] = m_pScaleformUI->Value_GetMember( m_AllIcons[RI_BOMB_ICON_PACKAGE], "BombAbove" );
m_AllIcons[RI_BOMB_ICON_BOMB_BELOW] = m_pScaleformUI->Value_GetMember( m_AllIcons[RI_BOMB_ICON_PACKAGE], "BombBelow" );
}
for ( int i = 0; i < RI_NUM_ICONS; i++ )
{
if ( m_AllIcons[i] )
{
m_pScaleformUI->Value_SetVisible( m_AllIcons[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 );
}
else
{
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hidePanel", NULL, 0 );
}
}
void SFMapOverview::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 SFMapOverview::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();
RemoveAllGrenades();
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_AllIcons[i] );
}
m_bFlashReady = false;
m_cDesiredMapName[0] = 0;
m_cLoadedMapName[0] = 0;
m_bActive = false;
return true;
}
// /*********************************************************
// * set up the background map
// */
void SFMapOverview::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;
}
// TODO release old texture ?
m_MapOrigin.x = MapKeyValues->GetInt( "pos_x" );
m_MapOrigin.y = MapKeyValues->GetInt( "pos_y" );
m_MapOrigin.z = 0;
m_fMapScale = MapKeyValues->GetFloat( "scale", 1.0f );
m_fWorldToPixelScale = 1.0f / m_fMapScale;
m_fWorldToRadarScale = m_fWorldToPixelScale * m_fPixelToRadarScale;
MapKeyValues->deleteThis();
}
void SFMapOverview::FlashLoadMap( const char* pMapName )
{
const char* pMapToLoad = pMapName ? pMapName : m_cDesiredMapName;
if ( V_strcmp( pMapToLoad, m_cLoadedMapName ) )
{
if ( m_bFlashReady )
{
if ( pMapToLoad != m_cDesiredMapName )
{
V_strncpy( m_cDesiredMapName, pMapToLoad, sizeof( m_cDesiredMapName )+1 );
}
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
{
m_pScaleformUI->ValueArray_SetElement( args, 0, pMapToLoad );
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "loadMap", args, 1 );
}
}
else
{
if ( pMapToLoad != m_cDesiredMapName )
{
V_strncpy( m_cDesiredMapName, pMapToLoad, sizeof( m_cDesiredMapName )+1 );
}
}
}
}
void SFMapOverview::MapLoaded( SCALEFORM_CALLBACK_ARGS_DECL )
{
// flash passes in the scaledsize / image size
m_fMapSize = ( float )pui->Params_GetArgAsNumber( obj, 0 );
m_fPixelToRadarScale = ( float )pui->Params_GetArgAsNumber( obj, 1 );
// m_MapOrigin.x = -(m_fMapSize/2);
// m_MapOrigin.y = -(m_fMapSize/2);
m_fWorldToRadarScale = m_fWorldToPixelScale * m_fPixelToRadarScale;
V_strncpy( m_cLoadedMapName, m_cDesiredMapName, sizeof( m_cLoadedMapName )+1 );
//Get the world's extent
C_World *world = GetClientWorldEntity();
if ( !world )
return;
Vector worldCenter = ( world->m_WorldMins + world->m_WorldMaxs ) * 0.5f;
}
void SFMapOverview::ToggleOverviewMap( SCALEFORM_CALLBACK_ARGS_DECL )
{
ShowMapOverview( !IsMapOverviewShown() );
}
// /**********************************************
// * reset functions
// */
//
//
void SFMapOverview::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( SFMapOverviewHostageIcons::HI_UNUSED );
}
RemoveAllGrenades();
RemoveAllDefusers();
}
m_iNumGoalIcons = 0;
m_bGotGoalIcons = false;
ResetRoundVariables();
}
void SFMapOverview::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;
ApplySpectatorModes(); // reapply here to make sure it stays when it's supposed to
ConVarRef mp_defuser_allocation( "mp_defuser_allocation" );
m_bTrackDefusers = ( mp_defuser_allocation.GetInt() == DefuserAllocation::Random );
if ( bResetGlobalStates )
{
m_nBombEntIndex = -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();
CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer && (pLocalPlayer->GetObserverMode() == OBS_MODE_NONE ) )
ShowMapOverview( false );
}
void SFMapOverview::ShowMapOverview( bool bValue )
{
if ( bValue == true && !CanShowOverview() )
return;
ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal();
if ( mode )
{
mode->ReloadScheme();
}
m_bShowMapOverview = bValue;
}
void SFMapOverview::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( SFMapOverviewHostageIcons::HI_UNUSED );
}
}
if ( bResetGlobalStates )
{
RemoveAllGrenades();
RemoveAllDefusers();
}
ResetRoundVariables( bResetGlobalStates );
}
void SFMapOverview::ResetRound( void )
{
ResetRadar( true );
RefreshGraphs();
}
void SFMapOverview::RefreshGraphs( void )
{
g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "onRefresh", 0, NULL );
}
// /*****************************************************
// * player icon loading / creating
// */
//
bool SFMapOverview::LazyUpdateIconArray( SFMapOverviewIconPackage* pArray, int lastIndex )
{
bool result = true;
int i;
SFMapOverviewIconPackage* 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 SFMapOverview::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_Grenades, m_iLastGrenadeIndex ) && m_bGotPlayerIcons;
m_bGotPlayerIcons = LazyUpdateIconArray( m_Defusers, m_iLastDefuserIndex ) && m_bGotPlayerIcons;
}
bool SFMapOverview::LazyCreateIconPackage( SFMapOverviewIconPackage* 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, "overviewCreateIconPack", args, 2 );
pIconPack->Init( m_pScaleformUI, result );
if ( result )
{
m_pScaleformUI->ReleaseValue( result );
}
}
return true;
}
else
{
return false;
}
}
void SFMapOverview::InitIconPackage( SFMapOverviewIconPackage* 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 SFMapOverview::RemoveIconPackage( SFMapOverviewIconPackage* 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
// */
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::CreatePlayer( int index )
{
SFMapOverviewIconPackage* pPackage = GetRadarPlayer( index );
InitIconPackage( pPackage, index, ICON_PACK_PLAYER );
m_iLastPlayerIndex = MAX( index, m_iLastPlayerIndex );
return pPackage;
}
void SFMapOverview::ResetPlayer( int index )
{
SFMapOverviewIconPackage* pPackage = GetRadarPlayer( index );
if ( pPackage->m_bIsActive )
{
pPackage->StartRound();
}
UpdatePlayerNameAndNumber( pPackage );
}
void SFMapOverview::RemovePlayer( int index )
{
RemoveIconPackage( GetRadarPlayer( index ) );
if ( index == m_iLastPlayerIndex )
{
while( m_iLastPlayerIndex >= 0 && !m_Players[m_iLastPlayerIndex].m_bIsActive )
{
m_iLastPlayerIndex--;
}
}
UpdateAllPlayerNamesAndNumbers();
}
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::CreateHostage( int index )
{
SFMapOverviewIconPackage* pPackage = GetRadarHostage( index );
InitIconPackage( pPackage, index, ICON_PACK_HOSTAGE );
m_iLastHostageIndex = MAX( index, m_iLastHostageIndex );
return pPackage;
}
void SFMapOverview::ResetHostage( int index )
{
SFMapOverviewIconPackage* pPackage = GetRadarHostage( index );
if ( pPackage->m_bIsActive )
{
pPackage->StartRound();
}
}
void SFMapOverview::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++ )
{
SFMapOverviewIconPackage* 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 SFMapOverview::RemoveHostage( int index )
{
RemoveIconPackage( GetRadarHostage( index ) );
if ( index == m_iLastHostageIndex )
{
while( m_iLastHostageIndex >= 0 && !m_Hostages[m_iLastHostageIndex].m_bIsActive )
{
m_iLastHostageIndex--;
}
}
}
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::CreateGrenade( int entityID, int nGrenadeType )
{
SFMapOverviewIconPackage* pPackage = NULL;
int index = m_iLastGrenadeIndex+1;
for ( int i = 0; i <= m_iLastGrenadeIndex; i++ )
{
if ( !m_Grenades[i].m_bIsActive )
{
index = i;
break;
}
}
if ( index < MAX_GRENADES )
{
pPackage = GetRadarGrenade( index );
InitIconPackage( pPackage, index, ICON_PACK_GRENADES );
pPackage->m_iEntityID = entityID;
pPackage->m_fRoundStartTime = TIMER_INIT;
m_iLastGrenadeIndex = MAX( index, m_iLastGrenadeIndex );
}
return pPackage;
}
void SFMapOverview::RemoveAllGrenades( void )
{
for ( int i = 0; i <= m_iLastGrenadeIndex; i++ )
{
if ( m_Grenades[i].m_bIsActive )
{
RemoveGrenade( i );
}
}
}
void SFMapOverview::RemoveGrenade( int index )
{
RemoveIconPackage( GetRadarGrenade( index ) );
if ( index == m_iLastGrenadeIndex )
{
while( m_iLastGrenadeIndex >= 0 && !m_Grenades[m_iLastGrenadeIndex].m_bIsActive )
{
m_iLastGrenadeIndex--;
}
}
}
SFMapOverview::SFMapOverviewIconPackage * SFMapOverview::GetDefuser( int nEntityID, bool bCreateIfNotFound )
{
SFMapOverviewIconPackage * pResult = NULL;
int nIndex = GetDefuseIndexFromEntityID( nEntityID );
if ( nIndex != INVALID_INDEX )
{
pResult = GetRadarDefuser( nIndex );
}
if ( pResult == NULL && bCreateIfNotFound )
{
pResult = CreateDefuser( nEntityID );
}
return pResult;
}
void SFMapOverview::SetDefuserPos( int nEntityID, int x, int y, int z, int a )
{
if ( !m_bTrackDefusers )
{
return;
}
SFMapOverviewIconPackage * 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
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::CreateDefuser( int nEntityID )
{
if ( !m_bTrackDefusers )
{
return NULL;
}
SFMapOverviewIconPackage* 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 SFMapOverview::RemoveAllDefusers( void )
{
for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
{
if ( m_Defusers[i].m_bIsActive )
{
RemoveDefuser( i );
}
}
}
void SFMapOverview::RemoveDefuser( int index )
{
RemoveIconPackage( GetRadarDefuser( index ) );
if ( index == m_iLastDefuserIndex )
{
while( m_iLastDefuserIndex >= 0 && !m_Defusers[m_iLastDefuserIndex].m_bIsActive )
{
m_iLastDefuserIndex--;
}
}
}
void SFMapOverview::SetPlayerTeam( int index, int team )
{
SFMapOverviewIconPackage* pPlayer = GetRadarPlayer( index );
pPlayer->SetPlayerTeam( team );
}
int SFMapOverview::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 SFMapOverview::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 SFMapOverview::GetGrenadeIndexFromEntityID( int entityID )
{
for ( int i = 0; i <= m_iLastGrenadeIndex; i++ )
{
if ( m_Grenades[i].m_bIsActive && m_Grenades[i].m_iEntityID == entityID )
{
return i;
}
}
return INVALID_INDEX;
}
int SFMapOverview::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;
}
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::GetRadarPlayer( int index )
{
return &m_Players[index];
}
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::GetRadarHostage( int index )
{
return &m_Hostages[index];
}
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::GetRadarGrenade( int index )
{
return &m_Grenades[index];
}
SFMapOverview::SFMapOverviewIconPackage* SFMapOverview::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 SFMapOverview::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
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" );
}
// 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();
// 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 )
{
SFMapOverviewIconPackage* pPlayerIcon = NULL;
pPlayerIcon = GetRadarPlayer( nEntityID - 1 );
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
{
SFMapOverviewIconPackage* 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;
}
void SFMapOverview::UpdateAllPlayerNamesAndNumbers( void )
{
//int nMaxPlayers = CCSGameRules::GetMaxPlayers();
for ( int i = 0; i <= MAX_PLAYERS; ++i )
{
SFMapOverviewIconPackage* pPackage = GetRadarPlayer( i );
if ( pPackage )
UpdatePlayerNameAndNumber( pPackage );
}
}
void SFMapOverview::UpdatePlayerNameAndNumber( SFMapOverviewIconPackage* pPackage )
{
int nMaxPlayers = CCSGameRules::GetMaxPlayers();
// update the player number
SFHudTeamCounter* pTeamCounter = GET_HUDELEMENT( SFHudTeamCounter );
if ( pPackage && pPackage->m_Icons[PI_PLAYER_NUMBER] && pPackage->m_Icons[PI_PLAYER_NAME_CT] && pPackage->m_Icons[PI_PLAYER_NAME_T] )
{
if ( pTeamCounter )
{
int pidx = pTeamCounter->GetPlayerSlotIndex( pPackage->m_iEntityID );
if ( pidx != -1 )
{
pidx += 1;
if ( pidx == 10 )
pidx = 0;
ISFTextObject* textPanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember( pPackage->m_Icons[PI_PLAYER_NUMBER], "Text" );
if ( textPanel )
{
CBasePlayer * pPlayer = CBasePlayer::GetLocalPlayer();
bool bIsSpec = (pPlayer && (m_bShowAll || pPlayer->GetObserverMode() != OBS_MODE_NONE ));
WITH_SLOT_LOCKED
{
if ( nMaxPlayers <= 10 && bIsSpec )
textPanel->SetText( pidx );
else
textPanel->SetText( "" );
}
SafeReleaseSFTextObject( textPanel );
}
}
}
int nTeamSlot = PI_PLAYER_NAME_CT;
if ( pPackage->m_iPlayerType == PI_T )
nTeamSlot = PI_PLAYER_NAME_T;
ISFTextObject* textPanelName = g_pScaleformUI->TextObject_MakeTextObjectFromMember( pPackage->m_Icons[nTeamSlot], "Text" );
if ( textPanelName )
{
WITH_SLOT_LOCKED
{
textPanelName->SetText( pPackage->m_wcName );
}
SafeReleaseSFTextObject( textPanelName );
}
}
}
//handles all game event messages ( first looks them up in map so there's no long list of strcmps )
void SFMapOverview::FireGameEvent( IGameEvent *event )
{
const char* eventName = event->GetName();
int elementIndex = m_messageMap.Find( eventName );
if ( elementIndex == m_messageMap.InvalidIndex() )
{
return;
}
SF_SPLITSCREEN_PLAYER_GUARD();
CBasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
int EventUserID = event->GetInt( "userid", -1 );
int LocalPlayerID = ( pLocalPlayer != NULL ) ? pLocalPlayer->GetUserID() : -2;
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();
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;
}
SFMapOverviewIconPackage* pPackage = CreatePlayer( index );
if ( messageTypeIndex == PLAYER_CONNECT )
{
pPackage->SetPlayerTeam( TEAM_SPECTATOR );
}
pPackage->m_iEntityID = userID;
const char* name = event->GetString( "name","unknown" );
if ( CDemoPlaybackParameters_t const *pParameters = engine->GetDemoPlaybackParameters() )
{
if ( pParameters->m_bAnonymousPlayerIdentity )
name = ""; // suppress names for anonymous playback
}
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;
}
SFMapOverviewIconPackage* pPackage = GetRadarPlayer( playerIndex );
pPackage->SetPlayerTeam( event->GetInt( "team" ) );
}
break;
case PLAYER_DEATH:
{
int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
if ( playerIndex == INVALID_INDEX )
{
return;
}
SFMapOverviewIconPackage* 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 );
}
}
break;
case PLAYER_SPAWN:
{
if ( EventUserID == LocalPlayerID )
{
m_bShowMapOverview = false;
}
int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
if ( playerIndex != INVALID_INDEX )
{
SFMapOverviewIconPackage* pPackage = GetRadarPlayer( playerIndex );
pPackage->m_Health = 100;
UpdatePlayerNameAndNumber( 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;
}
SFMapOverviewIconPackage* 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;
}
SFMapOverviewIconPackage* 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;
}
break;
case BOMB_PICKUP:
{
m_bBombDropped = false;
m_nBombEntIndex = -1;
}
break;
case BOMB_DROPPED:
{
m_nBombEntIndex = event->GetInt( "entindex", -1 );
m_bBombDropped = true;
}
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:
{
if ( pLocalPlayer )
{
int userID = event->GetInt( "userid" );
CBasePlayer* player = UTIL_PlayerByUserId( userID );
if ( player )
{
bool bShowGrenade = false;
// if it was placed by a player on our team or if we are a spectator, show the grenade as a grenade icon
// otherwise, we're going to show it as if it were a fake player
if ( player->GetAssociatedTeamNumber() == pLocalPlayer->GetAssociatedTeamNumber() || m_bShowAll )
bShowGrenade = true;
int entityID = event->GetInt( "entityid" );
int teamNumber = player->GetAssociatedTeamNumber();
SFMapOverviewIconPackage* pPackage = CreateGrenade( entityID, PI_GRENADE_DECOY );
if ( pPackage )
{
if ( bShowGrenade )
pPackage->SetGrenadeType( PI_GRENADE_DECOY );
else
{
pPackage->SetPlayerTeam( teamNumber );
pPackage->SetIsSpotted( true );
}
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 = GetGrenadeIndexFromEntityID( entityID );
if ( i != INVALID_INDEX )
{
SFMapOverviewIconPackage* pPackage = GetRadarGrenade( i );
pPackage->SetGrenadeExpireTime( gpGlobals->curtime );
SetIconPackagePosition( pPackage );
}
STEAMWORKS_TESTSECRET_AMORTIZE( 23 );
}
break;
case HE_DETONATE:
{
int entityID = event->GetInt( "entityid" );
int userID = event->GetInt( "userid" );
CBasePlayer* player = UTIL_PlayerByUserId( userID );
if ( pLocalPlayer && player )
{
// if it was placed by a player on our team or if we are a spectator, show the grenade as usually
// otherwise, we don't show it at all
Vector vecGrenade = Vector( ( float )event->GetInt( "x" ), ( float )event->GetInt( "y" ), 0 );
if ( (player->GetAssociatedTeamNumber() == pLocalPlayer->GetAssociatedTeamNumber() && IsEnemyCloseEnoughToShow( vecGrenade )) || m_bShowAll )
{
SFMapOverviewIconPackage* pPackage = CreateGrenade( entityID, PI_GRENADE_HE );
if ( pPackage )
{
pPackage->SetGrenadeType( PI_GRENADE_HE );
pPackage->SetGrenadeExpireTime( gpGlobals->curtime );
pPackage->m_Position.Init( vecGrenade.x, vecGrenade.y, 0.0f );
pPackage->m_Angle.Init( 0.0f, RandomFloat( 0.0f, 360.0f ), 0.0f );
SetIconPackagePosition( pPackage );
}
}
}
STEAMWORKS_TESTSECRET_AMORTIZE( 19 );
}
break;
case FLASH_DETONATE:
{
int entityID = event->GetInt( "entityid" );
int userID = event->GetInt( "userid" );
CBasePlayer* player = UTIL_PlayerByUserId( userID );
if ( pLocalPlayer && player )
{
// if it was placed by a player on our team or if we are a spectator, show the grenade as usually
// otherwise, we don't show it at all
Vector vecGrenade = Vector( ( float )event->GetInt( "x" ), ( float )event->GetInt( "y" ), 0 );
if ( (player->GetAssociatedTeamNumber() == pLocalPlayer->GetAssociatedTeamNumber() && IsEnemyCloseEnoughToShow( vecGrenade )) || m_bShowAll )
{
SFMapOverviewIconPackage* pPackage = CreateGrenade( entityID, PI_GRENADE_FLASH );
if ( pPackage )
{
pPackage->SetGrenadeType( PI_GRENADE_FLASH );
pPackage->SetGrenadeExpireTime( gpGlobals->curtime );
pPackage->m_Position.Init( vecGrenade.x, vecGrenade.y, 0.0f );
pPackage->m_Angle.Init( 0.0f, RandomFloat( 0.0f, 360.0f ), 0.0f );
SetIconPackagePosition( pPackage );
}
}
}
STEAMWORKS_TESTSECRET_AMORTIZE( 17 );
}
break;
case SMOKE_DETONATE:
{
int entityID = event->GetInt( "entityid" );
int userID = event->GetInt( "userid" );
CBasePlayer* player = UTIL_PlayerByUserId( userID );
if ( pLocalPlayer && player )
{
// if it was placed by a player on our team or if we are a spectator, show the grenade as usually
// otherwise, we don't show it at all
Vector vecGrenade = Vector( ( float )event->GetInt( "x" ), ( float )event->GetInt( "y" ), 0 );
if ( (player->GetAssociatedTeamNumber() == pLocalPlayer->GetAssociatedTeamNumber() && IsEnemyCloseEnoughToShow( vecGrenade )) || m_bShowAll )
{
SFMapOverviewIconPackage* pPackage = CreateGrenade( entityID, PI_GRENADE_SMOKE );
if ( pPackage )
{
pPackage->SetGrenadeType( PI_GRENADE_SMOKE );
pPackage->m_Position.Init( vecGrenade.x, vecGrenade.y, 0.0f );
pPackage->m_Angle.Init( 0.0f, RandomFloat( 0.0f, 360.0f ), 0.0f );
SetIconPackagePosition( pPackage );
}
}
}
}
break;
case SMOKE_EXPIRE:
{
int entityID = event->GetInt( "entityid" );
int i = GetGrenadeIndexFromEntityID( entityID );
if ( i != INVALID_INDEX )
{
SFMapOverviewIconPackage* pPackage = GetRadarGrenade( i );
pPackage->SetGrenadeExpireTime( gpGlobals->curtime );
SetIconPackagePosition( pPackage );
}
STEAMWORKS_TESTSECRET_AMORTIZE( 11 );
}
break;
case MOLOTOV_DETONATE:
{
int entityID = event->GetInt( "entityid" );
int userID = event->GetInt( "userid" );
CBasePlayer* player = UTIL_PlayerByUserId( userID );
if ( pLocalPlayer && player )
{
// if it was placed by a player on our team or if we are a spectator, show the grenade as usually
// otherwise, we don't show it at all
Vector vecGrenade = Vector( ( float )event->GetInt( "x" ), ( float )event->GetInt( "y" ), 0 );
if ( (player->GetAssociatedTeamNumber() == pLocalPlayer->GetAssociatedTeamNumber() && IsEnemyCloseEnoughToShow( vecGrenade )) || m_bShowAll )
{
SFMapOverviewIconPackage* pPackage = CreateGrenade( entityID, PI_GRENADE_MOLOTOV );
if ( pPackage )
{
pPackage->SetGrenadeType( PI_GRENADE_MOLOTOV );
pPackage->m_Position.Init( vecGrenade.x, vecGrenade.y, 0.0f );
pPackage->m_Angle.Init( 0.0f, RandomFloat( 0.0f, 360.0f ), 0.0f );
SetIconPackagePosition( pPackage );
}
}
}
}
break;
case MOLOTOV_EXPIRE:
{
int entityID = event->GetInt( "entityid" );
int i = GetGrenadeIndexFromEntityID( entityID );
if ( i != INVALID_INDEX )
{
SFMapOverviewIconPackage* pPackage = GetRadarGrenade( i );
pPackage->SetGrenadeExpireTime( gpGlobals->curtime );
SetIconPackagePosition( pPackage );
}
STEAMWORKS_TESTSECRET_AMORTIZE( 19 );
}
break;
case BOT_TAKEOVER:
{
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pLocalPlayer )
{
int userID = event->GetInt( "userid" );
int localID = pLocalPlayer->GetUserID();
if (localID == userID )
{
ResetRadar( false );
}
}
}
break;
default:
break;
}
}
//
//
// /*****************************************************
// * these set lazy update the icons and text based
// * on the values in the state variables
// */
//
void SFMapOverview::SetupIconsFromStates( void )
{
uint64 newFlags = 0;
if ( CSGameRules()->IsBombDefuseMap() )
{
// check to see if the bomb exists before assuming the first exists and trying to get data from it
if ( !m_bBombDefused && m_bBombPlanted && g_PlantedC4s.Count() > 0 )
{
float fPercent = ( g_PlantedC4s[0]->GetDetonationProgress() * 100.0f );
if ( fPercent > 60.0f )
{
newFlags |= 1 << RI_BOMB_IS_PLANTED;
}
else if ( fPercent > 30.0f )
{
newFlags |= 1 << RI_BOMB_IS_PLANTED_MEDIUM;
}
else if ( fPercent > 0.0f )
{
newFlags |= 1 << RI_BOMB_IS_PLANTED_FAST;
}
}
if ( m_fBombAlpha > 0.0f )
{
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 = GetLocalOrInEyeCSPlayer();
if ( pLocalOrObserver )
{
if ( m_BombPosition.z > pLocalOrObserver->GetAbsOrigin().z + 180 )
newFlags |= 1 << RI_BOMB_ICON_BOMB_ABOVE;
else if ( m_BombPosition.z < pLocalOrObserver->GetAbsOrigin().z - 180 )
newFlags |= 1 << RI_BOMB_ICON_BOMB_BELOW;
}
}
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
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;
ScaleformDisplayInfo displayInfo;
displayInfo.SetAlpha( m_fBombAlpha * 100.0f );
int nBombCarryOffset = 0;
if ( ((newFlags & (1 << RI_BOMB_ICON_BOMB_T)) || (newFlags & (1 << RI_BOMB_ICON_BOMB_CT))) && !(newFlags & (1 << RI_BOMB_ICON_PLANTED)) )
{
nBombCarryOffset = 6;
}
displayInfo.SetX( mapPosition.x );
displayInfo.SetY( mapPosition.y + nBombCarryOffset );
displayInfo.SetRotation( -m_RadarRotation );
assert( m_AllIcons[RI_BOMB_ICON_PACKAGE] );
m_pScaleformUI->Value_SetDisplayInfo( m_AllIcons[RI_BOMB_ICON_PACKAGE], &displayInfo );
}
}
else if ( CSGameRules()->IsHostageRescueMap() )
{
if ( m_bShowingHostageZone )
{
newFlags |= 1 << RI_IN_HOSTAGE_ZONE;
}
}
if ( m_bShowingDashboard )
newFlags |= 1 << RI_DASHBOARD;
SetVisibilityFlags( newFlags );
}
void SFMapOverview::SetVisibilityFlags( uint64 newFlags )
{
newFlags &= ( ( 1 << RI_NUM_ICONS )-1 );
uint64 diffFlags = m_iCurrentVisibilityFlags ^ newFlags;
if ( diffFlags )
{
for ( int i = 0; i < RI_NUM_ICONS && ( diffFlags != 0 ); i++, diffFlags >>= 1 )
{
if ( diffFlags & 1 )
{
if ( m_AllIcons[i] )
m_pScaleformUI->Value_SetVisible( m_AllIcons[i], ( newFlags & ( 1ll << i ) ) != 0 );
}
}
m_iCurrentVisibilityFlags = newFlags;
}
}
void SFMapOverview::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 SFMapOverview::WorldToRadar( const Vector& ptin, Vector& ptout )
{
ptout.x = ( ptin.x - m_MapOrigin.x ) * m_fWorldToRadarScale;
ptout.y = ( m_MapOrigin.y - ptin.y ) * m_fWorldToRadarScale;
ptout.z = 0;
}
void SFMapOverview::RadarToWorld( const Vector& ptin, Vector& ptout )
{
ptout.x = ( ptin.x + m_MapOrigin.x ) / m_fWorldToRadarScale;
ptout.y = ( m_MapOrigin.y + ptin.y ) / m_fWorldToRadarScale;
ptout.z = 0;
}
void SFMapOverview::PositionRadarViewpoint( void )
{
if ( !m_bFlashReady )
{
return;
}
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
CBasePlayer * pPlayer = CBasePlayer::GetLocalPlayer();
if( pPlayer == NULL )
{
pPlayer = GetSplitScreenViewPlayer( nSlot );
}
// [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 );
// }
// Get the world's extent
// C_World *world = GetClientWorldEntity();
// if ( !world )
// return;
//
// Vector worldCenter = ( world->m_WorldMins + world->m_WorldMaxs ) * 0.5f;
m_RadarViewpointWorld = Vector( m_MapOrigin.x, m_MapOrigin.y, 0 );//worldCenter;
//m_RadarViewpointWorld.z = 0;
WorldToRadar( m_RadarViewpointWorld, m_RadarViewpointMap );
m_RadarRotation = 0;
ScaleformDisplayInfo displayInfo;
if ( m_MapRotation )
{
displayInfo.SetRotation( m_RadarRotation );
m_pScaleformUI->Value_SetDisplayInfo( m_MapRotation, &displayInfo );
if ( m_MapTranslation )
{
displayInfo.Clear();
displayInfo.SetX( -(m_fMapSize/2) );
displayInfo.SetY( -(m_fMapSize/2) );
m_pScaleformUI->Value_SetDisplayInfo( m_MapTranslation, &displayInfo );
}
}
if ( m_IconRotation )
{
displayInfo.Clear();
displayInfo.SetRotation( m_RadarRotation );
m_pScaleformUI->Value_SetDisplayInfo( m_IconRotation, &displayInfo );
if ( m_IconTranslation )
{
displayInfo.Clear();
displayInfo.SetX( -(m_fMapSize/2) - 1 );
displayInfo.SetY( -(m_fMapSize/2) - 1 );
m_pScaleformUI->Value_SetDisplayInfo( m_IconTranslation, &displayInfo );
}
}
}
void SFMapOverview::PlaceGoalIcons( void )
{
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
if ( !pCSPR )
{
return;
}
SFMapOverviewGoalIcon* pwalk = m_GoalIcons;
Vector mapPosition;
ScaleformDisplayInfo displayInfo;
for ( int i = 0; i < m_iNumGoalIcons; i++ )
{
WorldToRadar( pwalk->m_Position, mapPosition );
if ( pwalk->m_Icon )
{
Vector newMapPosition = mapPosition;
newMapPosition -= m_RadarViewpointMap;
displayInfo.SetX( mapPosition.x );
displayInfo.SetY( mapPosition.y );
displayInfo.SetRotation( -m_RadarRotation );
m_pScaleformUI->Value_SetDisplayInfo( pwalk->m_Icon, &displayInfo );
}
pwalk++;
}
}
void SFMapOverview::SetIconPackagePosition( SFMapOverviewIconPackage* pPackage )
{
if ( !m_bFlashReady )
return;
Vector mapPosition;
ScaleformDisplayInfo displayInfo;
float mapAngle;
WorldToRadar( pPackage->m_Position, mapPosition );
Vector newMapPosition = mapPosition;
newMapPosition -= m_RadarViewpointMap;
pPackage->SetIsOffMap( false );
if ( pPackage->m_bIsDead || !pPackage->m_bIsSpotted )
{
mapAngle = -m_RadarRotation;
}
else
{
mapAngle = -pPackage->m_Angle[YAW]+90;
}
displayInfo.SetX( mapPosition.x );
displayInfo.SetY( mapPosition.y );
float flScale = mapoverview_icon_scale.GetFloat();
displayInfo.SetXScale( 120 * flScale );
displayInfo.SetYScale( 120 * flScale );
m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackage, &displayInfo );
// only rotated the sublayer, the stuff on top doesn't want to be rotated
//SFVALUE rotatedIcon;
//rotatedIcon = m_pScaleformUI->Value_GetMember( pPackage->m_IconPackage, "RotatedLayer" );
if ( pPackage->m_IconPackageRotate )
{
ScaleformDisplayInfo rotatedDisplayInfo;
rotatedDisplayInfo.SetRotation( mapAngle );
m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackageRotate, &rotatedDisplayInfo );
}
pPackage->SetupIconsFromStates();
}
void SFMapOverview::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;
bool bIsTerrorist = ( pLocalPlayer->GetAssociatedTeamNumber() == 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++;
}
}
else
{
// 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 )
{
SFMapOverviewIconPackage* 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 );
}
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++ )
{
SFMapOverviewIconPackage* pHostage = GetRadarHostage( i );
if ( pHostage->m_bIsActive )
{
C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( pHostage->m_iEntityID );
if ( pEntity && !pEntity->IsDormant() )
{
Assert( dynamic_cast<CHostage*>( pEntity ) );
pHostage->m_Position = pEntity->GetNetworkOrigin();
}
pHostage->SetIsSpotted( true );
SetIconPackagePosition( pHostage );
}
}
}
int hostageIndex = 0;
for ( int i = 0; i < iNumDeadHostages; i++ )
{
m_HostageStatusIcons[hostageIndex++].SetStatus( SFMapOverviewHostageIcons::HI_DEAD );
}
for ( int i = 0; i < iNumRescuedHostages; i++ )
{
m_HostageStatusIcons[hostageIndex++].SetStatus( SFMapOverviewHostageIcons::HI_RESCUED );
}
for ( int i = 0; i < iNumMovingHostages; i++ )
{
m_HostageStatusIcons[hostageIndex++].SetStatus( SFMapOverviewHostageIcons::HI_TRANSIT );
}
for ( int i = 0; i < iNumLiveHostages; i++ )
{
m_HostageStatusIcons[hostageIndex++].SetStatus( SFMapOverviewHostageIcons::HI_ALIVE );
}
for ( ; hostageIndex < MAX_HOSTAGES && m_HostageStatusIcons[hostageIndex].m_IconPackage != NULL; hostageIndex++ )
{
m_HostageStatusIcons[hostageIndex].SetStatus( SFMapOverviewHostageIcons::HI_UNUSED );
}
}
void SFMapOverview::UpdateAllDefusers( void )
{
if ( !m_bTrackDefusers )
{
return;
}
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
if( pLocalPlayer == NULL )
{
return;
}
for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
{
SFMapOverviewIconPackage * 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 SFMapOverview::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();
SFMapOverviewIconPackage* 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 ( pCSPR->IsConnected( 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 bObservingTarget = pLocalPlayer->GetObserverTarget() && (pLocalPlayer->GetObserverTarget() == pPlayer);
bool bHasValidPosition = playerIsActive || ( pwalk->m_Position.x != 0 || pwalk->m_Position.y != 0 );
Vector vecEnemy = pwalk->m_Position;
bool bPlayerSpotted = bObservingTarget || (( m_EntitySpotted.Get( playerIndex ) || ( playerIsActive && pPlayer->IsSpotted() ) )
&& (m_bShowAll || (!bSameTeam && IsEnemyCloseEnoughToShow( vecEnemy ))));
if ( pPlayer && bHasValidPosition && ( bSameTeam || m_bShowAll || bPlayerSpotted ) )
{
pwalk->SetIsSpotted( true );
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() && ( bPlayerSpotted || m_bShowAll ) )
{
m_bBombIsSpotted = true;
m_BombPosition = pwalk->m_Position;
}
// set is low health
pwalk->SetIsLowHealth( (playerIsActive && pPlayer->GetHealth() < 40) );
// set is selected
C_CSPlayer *pLocalOrObserver = ToCSPlayer( pLocalPlayer->GetObserverTarget() );
pwalk->SetIsSelected( pLocalOrObserver && pPlayer == pLocalOrObserver );
// set is flashed
pwalk->SetIsFlashed( pPlayer->IsBlinded() );
// set is firing
pwalk->SetIsFiring( (pPlayer->GetLastFiredWeaponTime() + 0.2) >= gpGlobals->curtime );
}
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 ) );
UpdatePlayerNameAndNumber( pwalk );
}
else
{
pwalk->SetIsSpotted( false );
pwalk->SetIsSpeaking( false );
}
// when a player dies the system reports the player's position as the position of
// the spectator camera. If we let that happen, the dead player's X migrates from
// the point they died to follow another player's position.
//
// so, never update the icon position for a dead player
if ( playerIsActive && pwalk->m_bIsSpotted && !pwalk->m_bIsDead )
{
// dkorus and pfreese: Changed from local origin and local angles to last networked version to address jitter issues for pax demo 2011
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->m_Angle = pPlayer->GetLocalAngles();
else
{
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
pwalk->m_Angle = MainViewAngles( nSlot );
}
if ( pPlayer->HasC4() )
{
m_BombPosition = pwalk->m_Position;
}
}
SetIconPackagePosition( pwalk );
}
}
}
bool SFMapOverview::IsEnemyCloseEnoughToShow( Vector vecEnemyPos )
{
//double check if spotted based on distance
// we're going to check the distance of this guy from all of the people on our team
// if they are outside the radius (more or less) of what the radar would allow us to see, consider them not spotted
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
if( !pLocalPlayer )
return false;
C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
if ( !pCSPR )
return false;
int localTeamNumber = pLocalPlayer->GetAssociatedTeamNumber();
bool bTooFar = true;
SFMapOverviewIconPackage* pTeammate = m_Players;
for ( int j = 0; j <= (m_iLastPlayerIndex); j++, pTeammate++ )
{
if ( pCSPR->IsConnected( (j+1) ) && localTeamNumber == pCSPR->GetTeam( (j+1) ) )
{
Vector toEnemy = pTeammate->m_Position - vecEnemyPos;
float dist = toEnemy.LengthSqr();
if ( dist <= NOTSPOTTEDRADIUS*NOTSPOTTEDRADIUS )
{
bTooFar = false;;
}
}
}
return !bTooFar;
}
void SFMapOverview::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;
}
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() ) && IsEnemyCloseEnoughToShow( pC4->GetNetworkOrigin() ) );
if ( bLocalPlayerCanSeeBomb && pC4 && !pC4->IsDormant() )
{
m_bBombIsSpotted = true;
m_BombPosition = pC4->GetNetworkOrigin();
}
}
}
}
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() && IsEnemyCloseEnoughToShow( pEntity->GetNetworkOrigin() ) );
if ( bLocalPlayerCanSeeBomb && pEntity && !pEntity->IsDormant() )
{
Assert( pEntity && FClassnameIs( pEntity, "weapon_c4" ) );
m_bBombIsSpotted = true;
m_BombPosition = pEntity->GetNetworkOrigin();
}
}
float now = gpGlobals->curtime;
bool drawBomb = false;
bool bBombPositionIsValid = ( m_BombPosition.x != 0 || m_BombPosition.y != 0 );
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();
}
}
void SFMapOverview::ApplySpectatorModes( void )
{
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
m_bShowAll = false;
m_iObserverMode = OBS_MODE_NONE;
if ( pLocalPlayer )
{
m_iObserverMode = pLocalPlayer->GetObserverMode();
if ( pLocalPlayer->IsSpectator() || pLocalPlayer->IsHLTV() )
{
m_bShowAll = true;
return;
}
}
// if ( m_iObserverMode != OBS_MODE_NONE )
// {
// // if we're observing in casual, then show everyone everywhere
// ConVarRef mp_forcecamera( "mp_forcecamera" );
// m_bShowAll = mp_forcecamera.GetInt() == OBS_ALLOW_ALL;
// }
}
void SFMapOverview::UpdateGrenades( void )
{
for ( int i = 0; i <= m_iLastGrenadeIndex; i++ )
{
SFMapOverviewIconPackage* pPackage = GetRadarGrenade( i );
if ( pPackage && pPackage->m_bIsActive )
{
SetIconPackagePosition( pPackage );
if ( !pPackage->IsVisible() )
{
RemoveGrenade( i );
}
}
}
}
void SFMapOverview::ProcessInput( void )
{
LazyCreateGoalIcons();
LazyCreatePlayerIcons();
ApplySpectatorModes();
PositionRadarViewpoint();
PlaceGoalIcons();
PlacePlayers();
PlaceHostages();
UpdateGrenades();
UpdateAllDefusers();
UpdateMiscIcons();
SetupIconsFromStates();
}
static inline bool Helper_AllowMapDrawing()
{
if ( mapoverview_allow_client_draw.GetBool() )
return true;
if ( sv_competitive_official_5v5.GetBool() )
return true;
if ( C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer() )
{
if ( pPlayer->IsHLTV() )
return true;
if ( pPlayer->IsSpectator() )
{
if ( CSGameRules() && CSGameRules()->IsQueuedMatchmaking() )
return true;
}
}
return false;
}
void SFMapOverview::AllowMapDrawing( SCALEFORM_CALLBACK_ARGS_DECL )
{
bool bAllow = Helper_AllowMapDrawing();
m_pScaleformUI->Params_SetResult( obj, bAllow );
}
void SFMapOverview::GetWorldDistance( SCALEFORM_CALLBACK_ARGS_DECL )
{
int x1 = ( float )pui->Params_GetArgAsNumber( obj, 0 );
int y1 = ( float )pui->Params_GetArgAsNumber( obj, 1 );
int x2 = ( float )pui->Params_GetArgAsNumber( obj, 2 );
int y2 = ( float )pui->Params_GetArgAsNumber( obj, 3 );
Vector vecStart;
Vector vecEnd;
RadarToWorld( Vector( x1, y1, 0 ), vecStart );
RadarToWorld( Vector( x2, y2, 0 ), vecEnd );
float flDist = vecStart.AsVector2D().DistTo( vecEnd.AsVector2D() );
m_pScaleformUI->Params_SetResult( obj, flDist );
}
/*
void SFMapOverview::GetNavPath( SCALEFORM_CALLBACK_ARGS_DECL )
{
int x1 = ( float )pui->Params_GetArgAsNumber( obj, 0 );
int y1 = ( float )pui->Params_GetArgAsNumber( obj, 1 );
int x2 = ( float )pui->Params_GetArgAsNumber( obj, 2 );
int y2 = ( float )pui->Params_GetArgAsNumber( obj, 3 );
Vector vecStart;
Vector vecEnd;
RadarToWorld( Vector( x1, y1, 0 ), vecStart );
RadarToWorld( Vector( x2, y2, 0 ), vecEnd );
CNavArea *navStartArea = TheNavMesh->GetNearestNavArea( vecStart );
CNavArea *navEndArea = TheNavMesh->GetNearestNavArea( vecEnd );
CNavArea *goalArea = NULL;
NavAreaBuildPath( tArea, ctArea, NULL, cost, &goalArea );
ShortestPathCost cost = ShortestPathCost();
float dist_left = NavAreaTravelDistance( TheNavMesh->GetNearestNavArea( ( *left )->GetAbsOrigin() ),
TheNavMesh->GetNearestNavArea( CSGameRules()->m_vecMainCTSpawnPos ),
cost );
float dist_right = NavAreaTravelDistance( TheNavMesh->GetNearestNavArea( ( *right )->GetAbsOrigin() ),
TheNavMesh->GetNearestNavArea( CSGameRules()->m_vecMainCTSpawnPos ),
cost );
//bool bAllow = Helper_AllowMapDrawing();
//m_pScaleformUI->Params_SetResult( obj, bAllow );
}
*/