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.
2226 lines
70 KiB
2226 lines
70 KiB
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "hud.h"
|
|
#include "hudelement.h"
|
|
#include "hud_element_helper.h"
|
|
#include "iclientmode.h"
|
|
#include "view.h"
|
|
#include "vgui_controls/Controls.h"
|
|
#include "vgui/ISurface.h"
|
|
#include "ivrenderview.h"
|
|
#include "scaleformui/scaleformui.h"
|
|
#include "sfhudreticle.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include "c_cs_hostage.h"
|
|
#include "c_cs_player.h"
|
|
#include "c_cs_playerresource.h"
|
|
#include "engineinterface.h"
|
|
#include "interfaces/interfaces.h"
|
|
#include "matchmaking/imatchframework.h"
|
|
#include "matchmaking/iplayermanager.h"
|
|
#include "gameui_util.h"
|
|
#include "c_plantedc4.h"
|
|
#include "sfhudfreezepanel.h"
|
|
#include "inputsystem/iinputsystem.h"
|
|
#include "voice_status.h"
|
|
#include "basepanel.h"
|
|
#include "cs_shareddefs.h"
|
|
#include "hltvcamera.h"
|
|
#include "cs_hud_weaponselection.h"
|
|
#include "HUD/sfhud_teamcounter.h"
|
|
#include "hltvreplaysystem.h"
|
|
#if !defined (NO_STEAM)
|
|
#include "steam/steam_api.h"
|
|
#endif
|
|
|
|
#ifdef SIXENSE
|
|
#include "sixense/in_sixense.h"
|
|
#endif
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//ConVar sfcrosshair( "sfcrosshair", "1", FCVAR_ARCHIVE | FCVAR_SS );
|
|
ConVar crosshair( "crosshair", "1", FCVAR_ARCHIVE | FCVAR_SS );
|
|
ConVar cl_observercrosshair( "cl_observercrosshair", "1", FCVAR_ARCHIVE | FCVAR_SS );
|
|
ConVar cl_fixedcrosshairgap( "cl_fixedcrosshairgap", "3", FCVAR_ARCHIVE | FCVAR_SS, "How big to make the gap between the pips in the fixed crosshair" );
|
|
ConVar lockMoveControllerRet( "lockMoveControllerRet", "0", FCVAR_ARCHIVE );
|
|
static ConVar hud_showtargetid( "hud_showtargetid", "1", FCVAR_ARCHIVE | FCVAR_SS, "Enables display of target names" );
|
|
|
|
//extern ConVar cl_dynamiccrosshair;
|
|
extern ConVar cl_teamid_overhead;
|
|
extern ConVar cl_teamid_overhead_maxdist;
|
|
extern ConVar cl_teamid_overhead_maxdist_spec;
|
|
extern ConVar voice_icons_method;
|
|
extern ConVar cl_crosshairstyle;
|
|
extern ConVar spec_show_xray;
|
|
extern ConVar cl_draw_only_deathnotices;
|
|
extern ConVar mp_hostages_takedamage;
|
|
static ConVar cl_teamid_overhead_name_alpha( "cl_teamid_overhead_name_alpha", "100", FCVAR_ARCHIVE | FCVAR_SS, "The max alpha the overhead ID names will draw as." );
|
|
static ConVar cl_teamid_overhead_name_fadetime( "cl_teamid_overhead_name_fadetime", "1.0", FCVAR_ARCHIVE | FCVAR_SS, "How long it takes for the overhad name to fade out once your crosshair has left the target." );
|
|
static ConVar mc_use_recoil_on_cursor( "mc_use_recoil_on_cursor", "0", 0 );
|
|
|
|
|
|
|
|
void fnTeamIDOverheadAlwaysCallback( IConVar *pConVar, const char *pOldValue, float flOldValue )
|
|
{
|
|
ConVarRef var( pConVar );
|
|
|
|
( GET_HUDELEMENT( SFHudReticle ) )->ToggleTeamEquipmentVisibility( var.GetInt() == 2 );
|
|
}
|
|
|
|
static ConVar cl_teamid_overhead_always( "cl_teamid_overhead_always", "0", FCVAR_ARCHIVE | FCVAR_RELEASE,"Always show team id over teammates. 1 = pips; 2 = pips, name, and equipment", fnTeamIDOverheadAlwaysCallback );
|
|
|
|
|
|
#define MAX_PLAYER_NAME_ID_PANELS 16
|
|
|
|
enum ID_TEXT_INDEX
|
|
{
|
|
IDTEXT_NONE,
|
|
IDTEXT_FOE,
|
|
IDTEXT_FRIEND,
|
|
IDTEXT_HOSTAGE
|
|
};
|
|
|
|
DECLARE_HUDELEMENT( SFHudReticle );
|
|
|
|
void IN_ShowTeamEquipmentDown( const CCommand &args )
|
|
{
|
|
( GET_HUDELEMENT( SFHudReticle ) )->ToggleTeamEquipmentVisibility( true );
|
|
}
|
|
|
|
void IN_ShowTeamEquipmentUp( const CCommand &args )
|
|
{
|
|
( GET_HUDELEMENT( SFHudReticle ) )->ToggleTeamEquipmentVisibility( false );
|
|
}
|
|
|
|
static ConCommand ShowAllTargetIDs( "+cl_show_team_equipment", IN_ShowTeamEquipmentDown );
|
|
static ConCommand UnShowAllTargetIDs( "-cl_show_team_equipment", IN_ShowTeamEquipmentUp );
|
|
|
|
|
|
|
|
|
|
SFUI_BEGIN_GAME_API_DEF
|
|
SFUI_DECL_METHOD_AS( OnSwapReticle, "SwapReticle" ),
|
|
SFUI_END_GAME_API_DEF( SFHudReticle, Reticle );
|
|
|
|
|
|
SFHudReticle::SFHudReticle( const char *value ) : SFHudFlashInterface( value ),
|
|
m_WeaponCrosshairHandle( NULL ),
|
|
m_TopPip( NULL ),
|
|
m_BottomPip( NULL ),
|
|
m_LeftPip( NULL ),
|
|
m_RightPip( NULL ),
|
|
m_topCrosshairArc( NULL ),
|
|
m_rightCrosshairArc( NULL ),
|
|
m_leftCrosshairArc( NULL ),
|
|
m_bottomCrosshairArc( NULL ),
|
|
m_FriendCrosshair( NULL ),
|
|
m_crosshairDot( NULL ),
|
|
m_blackRing( NULL ),
|
|
m_IDText( NULL ),
|
|
m_IDMovie( NULL ),
|
|
m_FlashedIcon( NULL ),
|
|
m_fIDTimer( 0.0f ),
|
|
m_bTextIDVisible( false ),
|
|
m_iReticleMode( RETICLE_MODE_NONE ),
|
|
m_bFriendlyCrosshairVisible( true ),
|
|
m_bEnemyCrosshairVisible( false ),
|
|
m_bFlashedIconFadingOut(true),
|
|
m_iLastGap( -1 ),
|
|
m_iLastSpread( -1 ),
|
|
m_dotX( 0.0f ),
|
|
m_dotY( 0.0f ),
|
|
m_blackRingX( 0.0f ),
|
|
m_blackRingY( 0.0f ),
|
|
m_friendIndicatorX( 0.0f ),
|
|
m_friendIndicatorY( 0.0f ),
|
|
m_IDMovieX( 0.0f ),
|
|
m_IDMovieY( 0.0f ),
|
|
m_bCrosshairPositionsInitialized( false )
|
|
{
|
|
// TODO Auto-generated constructor stub
|
|
SetHiddenBits( HIDEHUD_PLAYERDEAD | HIDEHUD_CROSSHAIR );
|
|
m_wcIDString[0] = 0;
|
|
m_bWantLateUpdate = true;
|
|
}
|
|
|
|
|
|
SFHudReticle::~SFHudReticle()
|
|
{
|
|
// TODO Auto-generated destructor stub
|
|
}
|
|
|
|
|
|
|
|
void SFHudReticle::ShowReticle( RETICLE_MODE mode, bool value )
|
|
{
|
|
SFVALUE handle = 0;
|
|
|
|
switch( mode )
|
|
{
|
|
case RETICLE_MODE_WEAPON:
|
|
handle = m_WeaponCrosshairHandle;
|
|
break;
|
|
|
|
case RETICLE_MODE_OBSERVER:
|
|
handle = m_ObserverCrosshairHandle;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( handle )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( handle, value );
|
|
}
|
|
|
|
}
|
|
|
|
void SFHudReticle::LockSlot( bool wantItLocked, bool& currentlyLocked )
|
|
{
|
|
if ( currentlyLocked != wantItLocked )
|
|
{
|
|
if ( wantItLocked )
|
|
LockScaleformSlot();
|
|
else
|
|
UnlockScaleformSlot();
|
|
currentlyLocked = wantItLocked;
|
|
}
|
|
}
|
|
|
|
extern ConVar weapon_debug_spread_show;
|
|
|
|
void SFHudReticle::ProcessInput( void )
|
|
{
|
|
if ( !FlashAPIIsValid() )
|
|
return;
|
|
|
|
SF_SPLITSCREEN_PLAYER_GUARD();
|
|
|
|
bool bShowFriendlyCrosshair = false;
|
|
RETICLE_MODE iDesiredReticleMode = RETICLE_MODE_NONE;
|
|
|
|
wchar_t wcNewString[ TEXTFIELD_LENGTH ];
|
|
wcNewString[0] = 0;
|
|
|
|
|
|
C_CSPlayer *pCSPlayer = GetHudPlayer();
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
// do crosshair calculations first because they can affect the
|
|
// display of the target id
|
|
|
|
bool bWantWeaponShown = false;
|
|
bool bHasWeapon = false;
|
|
bool bPlayerInInputMode = false;
|
|
bool bShowCrosshair = false;
|
|
bool bShowFriendEnemyDesignation = false;
|
|
bool bFriendlyCrosshairOkay = false;
|
|
bool bShowDroppedWeaponNames = false;
|
|
bool bCheckWeaponRange = false;
|
|
bool bWantEnemyCrosshair = false;
|
|
int iDesiredGap = -1;
|
|
int iDesiredSpread = -1;
|
|
float fDesiredFishtail = 0.0f;
|
|
int iObsMode = OBS_MODE_NONE;
|
|
|
|
/************************************
|
|
* the logic below is complicated, but here's what it means:
|
|
* 1 - If we're not in spectator mode, then only show a crosshair if we're not in an input mode
|
|
* and we have a weapon ( normally true ) and the weapon wants a crosshair.
|
|
* 2 - If we're in spectator in eye mode, show a crosshair if the weapon wants it
|
|
* but don't show the friendly target icon
|
|
* 3 - If we're in spectator roaming mode, show the spectator crosshair
|
|
* 4 - Otherwise show no crosshair
|
|
*/
|
|
|
|
if ( pLocalPlayer && crosshair.GetBool() )
|
|
{
|
|
iObsMode = pLocalPlayer->GetObserverMode();
|
|
|
|
switch( iObsMode )
|
|
{
|
|
case OBS_MODE_IN_EYE:
|
|
case OBS_MODE_ROAMING:
|
|
bShowCrosshair = true;
|
|
break;
|
|
|
|
case OBS_MODE_NONE:
|
|
bFriendlyCrosshairOkay = true;
|
|
bShowDroppedWeaponNames = true;
|
|
bShowCrosshair = true;
|
|
bShowFriendEnemyDesignation = true;
|
|
break;
|
|
|
|
default:
|
|
bShowCrosshair = false;
|
|
break;
|
|
}
|
|
|
|
#ifdef IRONSIGHT
|
|
CWeaponCSBase *pCSWeapon = pLocalPlayer->GetActiveCSWeapon();
|
|
if ( pCSWeapon && pCSWeapon->GetIronSightController() && !weapon_debug_spread_show.GetBool() )
|
|
{
|
|
bShowCrosshair = !pCSWeapon->GetIronSightController()->ShouldHideCrossHair();
|
|
}
|
|
#endif //IRONSIGHT
|
|
|
|
if ( bShowCrosshair && iObsMode != OBS_MODE_ROAMING )
|
|
{
|
|
if ( pLocalPlayer->IsInVGuiInputMode() || pLocalPlayer->IsInViewModelVGuiInputMode() )
|
|
bPlayerInInputMode = true;
|
|
else
|
|
{
|
|
CWeaponCSBase *pWeapon = ( CWeaponCSBase* )pCSPlayer->GetActiveWeapon();
|
|
|
|
if ( pWeapon )
|
|
{
|
|
bHasWeapon = true;
|
|
|
|
if ( pWeapon->WantReticleShown() )
|
|
{
|
|
if ( pWeapon->GetCSWeaponID() == WEAPON_TASER )
|
|
{
|
|
// When using the taser we don't want to change the reticle color until the
|
|
// target is in range.
|
|
bCheckWeaponRange = true;
|
|
}
|
|
|
|
bWantWeaponShown = true;
|
|
iDesiredSpread = pWeapon->GetReticleWeaponSpread();
|
|
iDesiredGap = pWeapon->GetReticleCrosshairGap();
|
|
fDesiredFishtail = pWeapon->GetAccuracyFishtail();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// the reticle mode is defaulted to NONE above (outside this clause) so
|
|
// we don't have to explicitly sent none
|
|
|
|
if ( bShowCrosshair )
|
|
{
|
|
if ( iObsMode == OBS_MODE_ROAMING )
|
|
{
|
|
iDesiredReticleMode = RETICLE_MODE_OBSERVER;
|
|
}
|
|
else if ( pLocalPlayer && !bPlayerInInputMode && bHasWeapon && bWantWeaponShown )
|
|
{
|
|
iDesiredReticleMode = RETICLE_MODE_WEAPON;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bShowBlankXHairID = false;
|
|
bool bIsHostage = false;
|
|
bool bLocalIsSpectatorViewer = CanSeeSpectatorOnlyTools();
|
|
bool bForceShowCenterID = false;
|
|
bool displayingTargetID = false;
|
|
|
|
bool bIsFullyBlinded = pCSPlayer && pCSPlayer->m_flFlashOverlayAlpha >= 180.0f;
|
|
bool bIsFlashed = pCSPlayer && pCSPlayer->m_flFlashBangTime > ( gpGlobals->curtime+0.5 );
|
|
if ( m_FlashedIcon && !cl_draw_only_deathnotices.GetBool() )
|
|
{
|
|
if ( pCSPlayer->m_flFlashOverlayAlpha > 0 && bLocalIsSpectatorViewer )
|
|
{
|
|
float flFlashFrac = 1.0 - clamp( pCSPlayer->m_flFlashOverlayAlpha / 210, 0, 1 );
|
|
// show flashed
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, flFlashFrac );
|
|
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "FlashFade", args, 1 );
|
|
}
|
|
m_bFlashedIconFadingOut = true;
|
|
}
|
|
else if ( m_bFlashedIconFadingOut )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
|
|
}
|
|
m_bFlashedIconFadingOut = false;
|
|
}
|
|
}
|
|
|
|
if ( hud_showtargetid.GetBool() )
|
|
{
|
|
// if we're still blinded, then leave everything just like it is
|
|
if ( !bLocalIsSpectatorViewer && bIsFlashed )
|
|
return;
|
|
|
|
// if we're spectating and the player we're observing is fully blind, say so in the target id
|
|
if ( iObsMode == OBS_MODE_IN_EYE && bIsFullyBlinded && !cl_draw_only_deathnotices.GetBool() )
|
|
{
|
|
displayingTargetID = true;
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( "#SFUIHUD_targetid_FLASHED" ), 0 );
|
|
}
|
|
else if ( ( iDesiredReticleMode != RETICLE_MODE_NONE ) || ( pCSPlayer->GetFOV() != pCSPlayer->GetDefaultFOV() ) )
|
|
{
|
|
// Get our target's ent index
|
|
int iEntIndex = hud_showtargetid.GetBool() ? pCSPlayer->GetIDTarget() : 0;
|
|
|
|
if ( iEntIndex )
|
|
{
|
|
C_CSPlayer *pPlayer = static_cast<C_CSPlayer*>( cl_entitylist->GetEnt( iEntIndex ) );
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
const char *printFormatString = NULL;
|
|
wchar_t wszClanTag[ MAX_PLAYER_NAME_LENGTH ];
|
|
wchar_t wszPlayerName[ MAX_DECORATED_PLAYER_NAME_LENGTH ];
|
|
wchar_t wszHealthText[ 10 ];
|
|
bool bShowHealth = false;
|
|
bool bShowPlayerName = false;
|
|
|
|
// Some entities we always want to check, cause the text may change
|
|
// even while we're looking at it
|
|
// Is it a player?
|
|
if ( IsPlayerIndex( iEntIndex ) )
|
|
{
|
|
// check player because they may have been endeadend
|
|
if ( pPlayer )
|
|
{
|
|
bShowPlayerName = true;
|
|
|
|
if ( pPlayer->IsOtherSameTeam( pLocalPlayer->GetTeamNumber() ) && !pPlayer->IsOtherEnemy( pLocalPlayer->entindex() ) )
|
|
{
|
|
printFormatString = ( bShowFriendEnemyDesignation ) ? "#SFUIHUD_playerid_sameteam" : "#SFUIHUD_playerid_specteam";
|
|
|
|
bShowFriendlyCrosshair = bFriendlyCrosshairOkay;
|
|
bShowHealth = true;
|
|
}
|
|
else if ( pLocalPlayer->GetTeamNumber() != TEAM_CT && pLocalPlayer->GetTeamNumber() != TEAM_TERRORIST )
|
|
{
|
|
printFormatString = "#SFUIHUD_playerid_noteam";
|
|
bShowFriendlyCrosshair = bFriendlyCrosshairOkay;
|
|
bShowHealth = true;
|
|
}
|
|
else
|
|
{
|
|
printFormatString = ( bShowFriendEnemyDesignation ) ? "#SFUIHUD_playerid_diffteam" : "#SFUIHUD_playerid_specteam";
|
|
|
|
bShowFriendlyCrosshair = false;
|
|
bWantEnemyCrosshair = bShowFriendEnemyDesignation;
|
|
|
|
if ( bWantEnemyCrosshair && bCheckWeaponRange )
|
|
{
|
|
CWeaponCSBase *pWeapon = ( CWeaponCSBase* )pCSPlayer->GetActiveWeapon();
|
|
|
|
if ( pWeapon )
|
|
{
|
|
float flWeaponRange = pWeapon->GetCSWpnData().GetRange();
|
|
|
|
vec_t length = VectorLength( pPlayer->WorldSpaceCenter() - pLocalPlayer->Weapon_ShootPosition() );
|
|
bWantEnemyCrosshair = ( length <= flWeaponRange );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// only get the name and health if necessary
|
|
if ( !( cl_teamid_overhead.GetInt() && bShowFriendlyCrosshair ) )
|
|
{
|
|
C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
|
|
|
|
if ( cs_PR )
|
|
{
|
|
cs_PR->GetDecoratedPlayerName( iEntIndex, wszPlayerName, sizeof( wszPlayerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
|
|
}
|
|
else
|
|
{
|
|
wszPlayerName[0] = L'\0';
|
|
}
|
|
|
|
if ( bShowHealth )
|
|
{
|
|
float flHealth = MAX( 0.0f, ( float )pPlayer->GetHealth() );
|
|
V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"%.0f%%", ( flHealth / ( float )pPlayer->GetMaxHealth() ) * 100 );
|
|
wszHealthText[ ARRAYSIZE( wszHealthText )-1 ] = '\0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wszPlayerName[0] = L'\0';
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
C_BaseEntity *pEnt = cl_entitylist->GetEnt( iEntIndex );
|
|
|
|
//Hostages!
|
|
C_CHostage *pHostage = NULL;
|
|
|
|
for( int i=0;i<g_Hostages.Count();i++ )
|
|
{
|
|
// compare entity pointers
|
|
if( g_Hostages[i] == pEnt )
|
|
{
|
|
pHostage = g_Hostages[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( pHostage != NULL )
|
|
{
|
|
float flHealth = MAX( 0.0f, ( float )pPlayer->GetHealth() );
|
|
V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"%.0f%%", ( flHealth / ( float )pHostage->GetMaxHealth() ) * 100 );
|
|
wszHealthText[ ARRAYSIZE( wszHealthText )-1 ] = '\0';
|
|
bShowFriendlyCrosshair = bFriendlyCrosshairOkay;
|
|
bShowHealth = mp_hostages_takedamage.GetBool();
|
|
bIsHostage = true;
|
|
|
|
Vector forward, up;
|
|
pLocalPlayer->EyeVectors( &forward, NULL, &up );
|
|
|
|
trace_t tr;
|
|
// Search for objects in a sphere (tests for entities that are not solid, yet still useable)
|
|
Vector searchCenter = pLocalPlayer->EyePosition();
|
|
int useableContents = MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS;
|
|
UTIL_TraceLine( searchCenter, searchCenter + forward * 1024, useableContents, pLocalPlayer, COLLISION_GROUP_NONE, &tr );
|
|
if ( tr.m_pEnt )
|
|
{
|
|
CConfigurationForHighPriorityUseEntity_t cfgUseHostageRule;
|
|
bool bValidHostageRule = pLocalPlayer->GetUseConfigurationForHighPriorityUseEntity( pHostage, cfgUseHostageRule );
|
|
// if we're outside use range, we're a terrorist or the hostage has a leader and it's not the player...
|
|
if ( !bValidHostageRule || !cfgUseHostageRule.UseByPlayerNow( pLocalPlayer, cfgUseHostageRule.k_EPlayerUseType_Start ) ||
|
|
pLocalPlayer->GetTeamNumber() == TEAM_TERRORIST || (pHostage->GetLeader() && pHostage->GetLeader() != pLocalPlayer) ||
|
|
(HOSTAGE_RULE_CAN_PICKUP && pLocalPlayer->m_hCarriedHostage != NULL) )
|
|
{
|
|
if ( pHostage->GetLeader() && pHostage->GetLeader() != pLocalPlayer)
|
|
{
|
|
if ( !bShowHealth )
|
|
printFormatString = "#SFUIHUD_hostageid_nh_following";
|
|
else
|
|
printFormatString = "#SFUIHUD_hostageid_following";
|
|
|
|
C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
|
|
char szClan[MAX_PLAYER_NAME_LENGTH];
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( szClan, wszClanTag, sizeof( wszClanTag ) );
|
|
if ( cs_PR )
|
|
{
|
|
cs_PR->GetDecoratedPlayerName( pHostage->GetLeader()->entindex(), wszPlayerName, sizeof( wszPlayerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
|
|
}
|
|
else
|
|
{
|
|
wszPlayerName[0] = L'\0';
|
|
}
|
|
bShowPlayerName = true;
|
|
}
|
|
else
|
|
{
|
|
if ( !bShowHealth )
|
|
{
|
|
//SFUIHUD_hostagename_nh
|
|
if ( CSGameRules()->IsPlayingCooperativeGametype() )
|
|
{
|
|
bShowPlayerName = true;
|
|
g_pVGuiLocalize->ConstructString( wszPlayerName, sizeof( wszPlayerName ), g_pVGuiLocalize->Find( pHostage->GetCustomHostageNameForMap( engine->GetLevelNameShort() ) ), 0 );
|
|
printFormatString = "#SFUIHUD_hostagename_nh";
|
|
}
|
|
else
|
|
printFormatString = "#SFUIHUD_hostageid_nh";
|
|
}
|
|
else
|
|
printFormatString = "#SFUIHUD_hostageid";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pHostage->GetLeader() == pLocalPlayer )
|
|
{
|
|
// if ( !bShowHealth )
|
|
// printFormatString = "#SFUIHUD_hostageid_nh_use_leave";
|
|
// else
|
|
// printFormatString = "#SFUIHUD_hostageid_use_leave";
|
|
}
|
|
else if ( !pHostage->GetLeader() )
|
|
{
|
|
if ( !bShowHealth )
|
|
printFormatString = "#SFUIHUD_hostageid_nh_use_lead";
|
|
else
|
|
printFormatString = "#SFUIHUD_hostageid_use_lead";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( printFormatString )
|
|
{
|
|
if ( cl_teamid_overhead.GetInt() && bShowFriendlyCrosshair && !bIsHostage )
|
|
{
|
|
Vector vDelta = pPlayer->EyePosition() - pLocalPlayer->EyePosition();
|
|
float flDistance = vDelta.Length();
|
|
|
|
if ( pPlayer->IsOtherSameTeam( pLocalPlayer->GetTeamNumber() ) && !pPlayer->IsOtherEnemy( pLocalPlayer->entindex() )
|
|
&& pPlayer->IsBot() && pPlayer->HasC4() && flDistance < PLAYER_USE_BOT_RADIUS )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( "#SFUIHUD_botid_request_bomb" ), 0 );
|
|
bForceShowCenterID = true;
|
|
}
|
|
else
|
|
{
|
|
V_snwprintf( wcNewString, ARRAYSIZE( wcNewString ), L"" );
|
|
bShowBlankXHairID = true;
|
|
}
|
|
|
|
displayingTargetID = true;
|
|
}
|
|
else
|
|
{
|
|
displayingTargetID = true;
|
|
if ( bShowPlayerName && bShowHealth )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 2, wszPlayerName, wszHealthText );
|
|
}
|
|
else if ( bShowPlayerName )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 1, wszPlayerName );
|
|
}
|
|
else if ( bShowHealth )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 1, wszHealthText );
|
|
}
|
|
else
|
|
{
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !displayingTargetID && bShowDroppedWeaponNames )
|
|
{
|
|
int weaponEntIndex = pCSPlayer->GetTargetedWeapon();
|
|
|
|
if ( weaponEntIndex > 0 ) //0 is a valid entity index, but will never be used for a weapon
|
|
{
|
|
C_BaseEntity *pEnt = cl_entitylist->GetEnt( weaponEntIndex );
|
|
C_PlantedC4 *pC4 = dynamic_cast<C_PlantedC4*>( pEnt );
|
|
if ( !pC4 )
|
|
{
|
|
CWeaponCSBase* weapon = static_cast<CWeaponCSBase*>( pEnt );
|
|
bool isWeaponAllowed = ( weapon && ( !weapon->IsA(WEAPON_TASER) /* || weapon->HasAnyAmmo()*/ ) ); // we allow players to pick up guns without ammo --mtw
|
|
|
|
CEconItemView *pItem = weapon->GetEconItemView();
|
|
wchar_t wcTargetWeaponFormatted[128];
|
|
if ( pItem && pItem->IsValid() )
|
|
{
|
|
const CEconItemRarityDefinition* pRarity = GetItemSchema()->GetRarityDefinition( pItem->GetRarity() );
|
|
const int kColorBufSize = 128;
|
|
wchar_t rwchColor[kColorBufSize];
|
|
Q_UTF8ToUnicode( GetHexColorForAttribColor( pRarity->GetAttribColor() ), rwchColor, kColorBufSize );
|
|
|
|
// Update target name
|
|
V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), L"<font color=\"" PRI_WS_FOR_WS L"\">" PRI_WS_FOR_WS L"</font>", rwchColor, pItem->GetItemName( true ) );
|
|
}
|
|
else
|
|
{
|
|
V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), PRI_WS_FOR_WS, g_pVGuiLocalize->Find( weapon->GetPrintName() ) );
|
|
}
|
|
|
|
//const char* szWeaponPrintName = ( pItem ? pItem->GetItemDefinition()->GetItemBaseName() : weapon->GetPrintName() );
|
|
|
|
if ( isWeaponAllowed && wcTargetWeaponFormatted )
|
|
{
|
|
displayingTargetID = true;
|
|
|
|
CSWeaponType nType = weapon->GetWeaponType();
|
|
if ( pCSPlayer->IsPrimaryOrSecondaryWeapon( nType ) )
|
|
{
|
|
// check to see if we are swapping weapons or if we are just filling in an empty weapon slot
|
|
bool bSwap = false;
|
|
if ( (nType == WEAPONTYPE_PISTOL && pCSPlayer->Weapon_GetSlot( WEAPON_SLOT_PISTOL )) || ( nType != WEAPONTYPE_PISTOL && pCSPlayer->Weapon_GetSlot( WEAPON_SLOT_RIFLE ) ) )
|
|
bSwap = true;
|
|
|
|
if ( bSwap )
|
|
{
|
|
//const wchar_t* wszWeaponText = g_pVGuiLocalize->Find( szWeaponPrintName );
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( "#SFUIHUD_weaponid_pickup" ), 1, wcTargetWeaponFormatted );
|
|
}
|
|
else
|
|
{
|
|
V_snwprintf( wcNewString, ARRAYSIZE( wcNewString ), PRI_WS_FOR_WS, wcTargetWeaponFormatted );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
V_snwprintf( wcNewString, ARRAYSIZE( wcNewString ), PRI_WS_FOR_WS, wcTargetWeaponFormatted );
|
|
displayingTargetID = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// player ID
|
|
FOR_EACH_VEC( m_playerIDs, i )
|
|
{
|
|
m_playerIDs[i].bActive = false;
|
|
}
|
|
|
|
{
|
|
MDLCACHE_CRITICAL_SECTION();
|
|
|
|
bool bIsPauseMenuActive = ( BasePanel() && BasePanel()->IsScaleformPauseMenuActive() );
|
|
bool bShowAllNamesForSpec = (bLocalIsSpectatorViewer && spec_show_xray.GetInt());
|
|
|
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
|
{
|
|
if ( bIsPauseMenuActive )
|
|
break;
|
|
|
|
//TODO: check whether they are an enemy as well
|
|
CCSPlayer* pOtherPlayer = ToCSPlayer( UTIL_PlayerByIndex( i ) );
|
|
|
|
bool bTurnedOff = false;
|
|
if ( cl_teamid_overhead.GetBool() == false || cl_draw_only_deathnotices.GetBool() == true )
|
|
bTurnedOff = true;
|
|
|
|
if ( bTurnedOff || !pLocalPlayer || !pOtherPlayer || !pOtherPlayer->IsAlive( ) || !pOtherPlayer->IsVisible( ) || ( pOtherPlayer == pCSPlayer && !input->CAM_IsThirdPersonOverview( ) ) )
|
|
continue;
|
|
|
|
if ( g_HltvReplaySystem.GetHltvReplayDelay() )
|
|
continue; // in replay, there's a clear indication of "You". People seem to not care about the other labels that add to visual noise.
|
|
static ConVarRef sv_show_voip_indicator_for_enemies( "sv_show_voip_indicator_for_enemies" );
|
|
if ( bShowAllNamesForSpec || (pCSPlayer->IsOtherSameTeam( pOtherPlayer->GetTeamNumber() ) && !pCSPlayer->IsOtherEnemy( pOtherPlayer ) ) || ( sv_show_voip_indicator_for_enemies.GetBool() && pOtherPlayer->IsPlayerTalkingOverVOIP() ) )
|
|
{
|
|
bool bSameTeam = pLocalPlayer->InSameTeam( pOtherPlayer );
|
|
bool bIsEnemy = pLocalPlayer->IsOtherEnemy( pOtherPlayer );
|
|
Vector vDelta = pOtherPlayer->EyePosition() - pCSPlayer->EyePosition();
|
|
float flDistance = vDelta.Length();
|
|
// get our spectator target
|
|
int nTargetSpec = g_bEngineIsHLTV ? HLTVCamera()->GetCurrentOrLastTarget() : (pLocalPlayer->GetObserverTarget() ? pLocalPlayer->GetObserverTarget()->entindex() : -1);
|
|
// max distance to draw the names is different depending on whether we are on team spectator or not
|
|
float flMaxDrawDist = bShowAllNamesForSpec ? cl_teamid_overhead_maxdist_spec.GetInt() : cl_teamid_overhead_maxdist.GetInt();
|
|
// always show the name for the player who is our target when roaming
|
|
if ( bShowAllNamesForSpec && nTargetSpec == pOtherPlayer->entindex() && (pLocalPlayer->GetObserverMode() == OBS_MODE_FIXED || pLocalPlayer->GetObserverMode() == OBS_MODE_ROAMING) )
|
|
flMaxDrawDist = 99999.9f;
|
|
|
|
if ( flDistance <= flMaxDrawDist )
|
|
{
|
|
Vector vecOtherPlayerEyes = pOtherPlayer->EyePosition() + Vector( 0, 0, 3 );
|
|
// other player is close enough, now make sure the local player is facing the other player.
|
|
Vector vecOtherPlayerPos = pOtherPlayer->EyePosition();
|
|
Vector forward;
|
|
AngleVectors(pCSPlayer->EyeAngles(), &forward, NULL, NULL);
|
|
Vector toAimSpot = vecOtherPlayerEyes - pCSPlayer->EyePosition();
|
|
float rangeToEnemy = toAimSpot.NormalizeInPlace();
|
|
float flTargetIDCone = DotProduct( toAimSpot, forward );
|
|
const float flViewCone = 0.5f;
|
|
|
|
bool bPlayerIsNotVisible = false;
|
|
|
|
// trace against world for enemies or if client doesn't want team id everywhere+
|
|
{
|
|
// if we can't trace to the player or if they are obscured by smoke, skip them
|
|
CBasePlayer *lastPlayerHit = NULL;
|
|
trace_t tr;
|
|
if ( pCSPlayer->IsAlive( ) && ( flTargetIDCone > flViewCone ) && !bShowAllNamesForSpec )
|
|
{
|
|
if ( LineGoesThroughSmoke( pCSPlayer->EyePosition(), vecOtherPlayerEyes, 1.0f ) )
|
|
{
|
|
if ( !ShouldShowAllFriendlyTargetIDs() || pCSPlayer->IsOtherEnemy( pOtherPlayer ) )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
bPlayerIsNotVisible = true;
|
|
}
|
|
|
|
}
|
|
|
|
UTIL_TraceLine( pCSPlayer->EyePosition(), vecOtherPlayerEyes, MASK_VISIBLE, pCSPlayer, COLLISION_GROUP_DEBRIS, &tr );
|
|
{
|
|
CTraceFilterSkipTwoEntities filter( pCSPlayer, lastPlayerHit, COLLISION_GROUP_DEBRIS );
|
|
|
|
// Check for player hitboxes extending outside their collision bounds
|
|
const float rayExtension = 40.0f;
|
|
UTIL_ClipTraceToPlayers( pCSPlayer->EyePosition(), vecOtherPlayerEyes + forward * rayExtension, MASK_VISIBLE, &filter, &tr );
|
|
if ( tr.fraction < 1 )
|
|
{
|
|
if ( !ShouldShowAllFriendlyTargetIDs() || pCSPlayer->IsOtherEnemy( pOtherPlayer ) )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
bPlayerIsNotVisible = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// aiming tolerance depends on how close the target is - closer targets subtend larger angles
|
|
float aimTolerance = 0.6f; //(float)cos( atan( 256 / rangeToEnemy ) );
|
|
|
|
int index = 0;
|
|
bool bExists = false;
|
|
|
|
// let's do this!
|
|
if ( bShowAllNamesForSpec || flTargetIDCone > flViewCone )
|
|
{
|
|
FOR_EACH_VEC( m_playerIDs, j )
|
|
{
|
|
if ( m_playerIDs[j].hPlayer.Get() == pOtherPlayer )
|
|
{
|
|
index = j;
|
|
bExists = true;
|
|
m_playerIDs[j].bActive = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int nIDIndex = pCSPlayer->GetIDTarget();
|
|
//Msg( "ID Index = %d\n", nIDIndex );
|
|
C_BaseEntity *pIDEnt = cl_entitylist->GetEnt( nIDIndex );
|
|
bool bShowIDName = CSGameRules()->IsFreezePeriod() || bShowAllNamesForSpec || ((pIDEnt == pOtherPlayer || !pCSPlayer->IsAlive()) && bSameTeam && !bIsEnemy);
|
|
|
|
if ( !bExists )
|
|
{
|
|
index = m_playerIDs.Count();
|
|
bExists = true;
|
|
|
|
bool bFriend = false;
|
|
|
|
C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
|
|
if ( cs_PR )
|
|
{
|
|
XUID nOtherXUID = cs_PR->GetXuid( pOtherPlayer->entindex() );
|
|
if ( g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetFriendByXUID( nOtherXUID ) )
|
|
{
|
|
bFriend = true;
|
|
}
|
|
}
|
|
|
|
AddNewPlayerID( pOtherPlayer, bShowIDName, bFriend );
|
|
}
|
|
|
|
if ( m_playerIDs.Count() > 0 && index < m_playerIDs.Count() )
|
|
{
|
|
// update the team number
|
|
m_playerIDs[index].nTeam = pOtherPlayer->GetTeamNumber();
|
|
|
|
bool bFlashedChanged = bLocalIsSpectatorViewer ? (m_playerIDs[index].bFlashedAmt != pOtherPlayer->m_flFlashOverlayAlpha) : false;
|
|
bool bHealthChanged = (m_playerIDs[index].nHealth != pOtherPlayer->GetHealth());
|
|
bool bUpdateNow = (m_playerIDs[index].flUpdateAt != 0 && m_playerIDs[index].flUpdateAt <= gpGlobals->curtime );
|
|
if ( bExists && ( /*CSGameRules()->IsFreezePeriod() ||*/ bUpdateNow || bHealthChanged || bFlashedChanged || m_playerIDs[index].bShowName != bShowIDName) )
|
|
{
|
|
if ( bShowIDName == false && m_playerIDs[index].bShowName == true )
|
|
{
|
|
m_playerIDs[index].flLastHighlightTime = gpGlobals->curtime;
|
|
}
|
|
|
|
if ( CSGameRules()->IsFreezePeriod() ) // update again in a bit if we're still in freeze time
|
|
m_playerIDs[index].flUpdateAt = gpGlobals->curtime + 0.5f;
|
|
else
|
|
m_playerIDs[index].flUpdateAt = 0;
|
|
|
|
m_playerIDs[index].bShowName = bShowIDName;
|
|
m_playerIDs[index].nHealth = pOtherPlayer->GetHealth();
|
|
UpdatePlayerID( pOtherPlayer, index, true );
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
float flScale = clamp( (float)atan( 512 / (rangeToEnemy*1.0) ), 0.6, 2 );
|
|
|
|
float flAlp = clamp( 1 - (rangeToEnemy / (flMaxDrawDist*0.75)), 0.25, 1 );
|
|
|
|
//Msg( "scale = %f, rangeToEnemy = %f\n", flScale, rangeToEnemy );
|
|
// adjust scale by the screen size
|
|
flScale *= clamp( 1-(600.0f/(float)ScreenHeight()), 0.25, 1 );
|
|
float flFadeRangeClose = 160;
|
|
if ( rangeToEnemy < flFadeRangeClose && !bShowIDName )
|
|
{
|
|
flAlp *= MAX( 0.25, (rangeToEnemy-(flFadeRangeClose*0.35))/(flFadeRangeClose*0.55) );
|
|
}
|
|
|
|
float flFadeEdge = (1-aimTolerance)*0.4;
|
|
if ( flTargetIDCone < (aimTolerance+flFadeEdge) && !bShowAllNamesForSpec )
|
|
{
|
|
float flFadeEdgeCur = flTargetIDCone - aimTolerance;
|
|
flAlp *= MAX( 0.3, flFadeEdgeCur/flFadeEdge );
|
|
}
|
|
|
|
if ( input->CAM_IsThirdPersonOverview() )
|
|
{
|
|
flScale = 0.8f;
|
|
flAlp = 1.0f;
|
|
}
|
|
|
|
// need to make sure that not only do we have a valid handle, but that the handle is of the correct type for GetType to handle it. Otherwise Scaleform just crashes.....
|
|
if ( m_playerIDs[index].panel && m_pScaleformUI->Value_GetType( m_playerIDs[index].panel ) == IScaleformUI::VT_DisplayObject )
|
|
{
|
|
// if the player is talking, hide the arrow and just show the talk icon
|
|
if ( m_playerIDs[index].arrowA && m_playerIDs[index].arrowB && m_playerIDs[index].arrowF && m_playerIDs[index].voiceIcon && m_playerIDs[index].defuseIcon )
|
|
{
|
|
bool bIsFriend = m_playerIDs[index].bFriend;
|
|
bool bVoiceActive = !bPlayerIsNotVisible && ( pOtherPlayer->IsPlayerTalkingOverVOIP( ) && ( ( bSameTeam && !bIsEnemy ) || sv_show_voip_indicator_for_enemies.GetBool( ) ) && voice_icons_method.GetInt( ) == 2 );
|
|
bool bIsDefusing = !bPlayerIsNotVisible && pOtherPlayer->m_bIsDefusing;
|
|
int flags = 0;
|
|
flags |= bIsFriend ? 1<<0 : 0;
|
|
flags |= bVoiceActive ? 1<<1 : 0;
|
|
flags |= bIsDefusing ? 1<<2 : 0;
|
|
if ( m_playerIDs[index].iconsFlag != flags )
|
|
{
|
|
ScaleformDisplayInfo dinfoA;
|
|
ScaleformDisplayInfo dinfoB;
|
|
ScaleformDisplayInfo dinfoF;
|
|
ScaleformDisplayInfo dinfoV;
|
|
ScaleformDisplayInfo dinfoD;
|
|
dinfoA.SetVisibility( !bVoiceActive && !bIsDefusing );
|
|
dinfoB.SetVisibility( !bVoiceActive && /*!bIsFriend &&*/ !bIsDefusing );
|
|
dinfoF.SetVisibility( !bVoiceActive && bIsFriend && !bIsDefusing );
|
|
dinfoV.SetVisibility( bVoiceActive );
|
|
dinfoD.SetVisibility( bIsDefusing && !bVoiceActive );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].arrowA, &dinfoA );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].arrowB, &dinfoB );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].arrowF, &dinfoF );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].voiceIcon, &dinfoV );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].defuseIcon, &dinfoD );
|
|
|
|
m_playerIDs[index].iconsFlag = flags;
|
|
}
|
|
}
|
|
|
|
// put the indicator right over their head
|
|
bool bHaveHeadBone = true;
|
|
// Make sure he's all the way on screen so his bone is correct
|
|
int iBIndex = -1;
|
|
{
|
|
iBIndex = pOtherPlayer->LookupBone( "ValveBiped.Bip01_Head" );
|
|
}
|
|
|
|
if( ( iBIndex == -1 ) || !pOtherPlayer->GetBaseAnimating()->isBoneAvailableForRead( iBIndex ) )
|
|
{
|
|
bHaveHeadBone = false;
|
|
}
|
|
|
|
Vector vecBone;
|
|
if ( bHaveHeadBone )
|
|
{
|
|
QAngle angBone;
|
|
pOtherPlayer->GetBonePosition( iBIndex, vecBone, angBone );
|
|
}
|
|
else
|
|
{
|
|
vecBone = (pOtherPlayer->EyePosition() - pOtherPlayer->GetAbsOrigin()) + Vector( 0.0f, 0.0f, 20 );
|
|
}
|
|
|
|
int iX, iY;
|
|
GetVectorInScreenSpace( vecBone + Vector( 0, 0, 9 ), iX, iY );
|
|
//GetTargetInScreenSpace( pFoundEnt, iX, iY );
|
|
ScaleformDisplayInfo dinfo;
|
|
dinfo.SetVisibility( true );
|
|
dinfo.SetAlpha( 140 * flAlp );
|
|
dinfo.SetX( iX );
|
|
dinfo.SetY( iY );
|
|
dinfo.SetXScale( 240 * flScale );
|
|
dinfo.SetYScale( 240 * flScale );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].panel, &dinfo );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End MDLCACHE_CRITICAL_SECTION()
|
|
|
|
// Don't remove players at this point in order to void adding them again (causing spikes)
|
|
|
|
FOR_EACH_VEC( m_playerIDs, k )
|
|
{
|
|
if ( m_playerIDs[ k ].bActive == false )
|
|
{
|
|
//RemoveID( k );
|
|
m_pScaleformUI->Value_SetVisible( m_playerIDs[ k ].panel, false );
|
|
}
|
|
}
|
|
|
|
if ( !ShouldShowAllFriendlyEquipment() )
|
|
{
|
|
FOR_EACH_VEC( m_playerIDs, l )
|
|
{
|
|
float flTimeToFadeOut = cl_teamid_overhead_name_fadetime.GetFloat();
|
|
float flExpireTime = m_playerIDs[l].flLastHighlightTime + flTimeToFadeOut;
|
|
int nMaxAlpha = cl_teamid_overhead_name_alpha.GetInt();
|
|
|
|
if ( m_playerIDs[l].bActive && m_playerIDs[l].bShowName == false && m_playerIDs[l].flNameAlpha > 0 )
|
|
{
|
|
float frac = ( flExpireTime - gpGlobals->curtime ) / flTimeToFadeOut;
|
|
int alpha = frac * nMaxAlpha;
|
|
|
|
SFVALUE animatedID = m_pScaleformUI->Value_GetMember( m_playerIDs[l].panel, "IDClip" );
|
|
SFVALUE textBG = m_pScaleformUI->Value_GetMember( m_playerIDs[l].panel, "IDTextBG" );
|
|
|
|
if ( animatedID /*&& animatedIDDrop*/ && textBG )
|
|
{
|
|
SFVALUE textmovie = m_pScaleformUI->Value_GetMember( animatedID, "IDTextMovie" );
|
|
|
|
if ( textmovie /*&& textDrop*/ )
|
|
{
|
|
ScaleformDisplayInfo dinfo;
|
|
ScaleformDisplayInfo dinfo2;
|
|
dinfo.SetAlpha( alpha );
|
|
dinfo2.SetAlpha( alpha/7 );
|
|
if ( alpha <= 0 || frac <= 0 )
|
|
{
|
|
alpha = 0;
|
|
dinfo.SetVisibility( false );
|
|
dinfo2.SetVisibility( false );
|
|
}
|
|
m_playerIDs[l].flNameAlpha = MAX( 0, alpha );
|
|
m_pScaleformUI->Value_SetDisplayInfo( textmovie, &dinfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( textBG, &dinfo2 );
|
|
|
|
SafeReleaseSFVALUE( textmovie );
|
|
}
|
|
|
|
SafeReleaseSFVALUE( animatedID );
|
|
SafeReleaseSFVALUE( textBG );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// now do all the stuff that might lock the slot
|
|
//0 = default
|
|
//1 = default static
|
|
//2 = classic standard
|
|
//3 = classic dynamic
|
|
//4 = classic static
|
|
if ( cl_crosshairstyle.GetInt() >= 2 )
|
|
//if ( !sfcrosshair.GetBool() )
|
|
{
|
|
iDesiredReticleMode = RETICLE_MODE_NONE;
|
|
}
|
|
|
|
bool bSlotIsLocked = false;
|
|
|
|
if ( displayingTargetID && (wcNewString[0] || bShowBlankXHairID) )
|
|
{
|
|
// this updates the text if necessary
|
|
if ( V_wcscmp( wcNewString, m_wcIDString ) )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
m_pScaleformUI->Value_SetTextHTML( m_IDText, m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( wcNewString ) );
|
|
V_wcsncpy( m_wcIDString, wcNewString, TEXTFIELD_LENGTH*sizeof( wchar_t ) );
|
|
}
|
|
|
|
// this shows/hides the friendly crosshair
|
|
if ( m_FriendCrosshair && ( bShowFriendlyCrosshair != m_bFriendlyCrosshairVisible ) )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, bShowFriendlyCrosshair );
|
|
m_bFriendlyCrosshairVisible = bShowFriendlyCrosshair;
|
|
}
|
|
|
|
// update the timer ( which turns the text field off after quarter a second
|
|
m_fIDTimer = gpGlobals->curtime + 0.25f;
|
|
|
|
// call the text field's show animation if it isn't already visible
|
|
if ( !m_bTextIDVisible && (bForceShowCenterID || cl_teamid_overhead.GetInt() == 0 || (cl_teamid_overhead.GetInt() > 0 && !bShowFriendlyCrosshair) || bIsHostage) )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "Show", NULL, 0 );
|
|
m_bTextIDVisible = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// hide the friendly crosshair since we're not looking at anything anymore
|
|
if ( m_bFriendlyCrosshairVisible )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, false );
|
|
m_bFriendlyCrosshairVisible = false;
|
|
}
|
|
|
|
// once our timer has run out, call the hide animation for the text
|
|
if ( m_bTextIDVisible && gpGlobals->curtime >= m_fIDTimer )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "Hide", NULL, 0 );
|
|
m_bTextIDVisible = false;
|
|
}
|
|
}
|
|
|
|
if ( bWantEnemyCrosshair != m_bEnemyCrosshairVisible )
|
|
{
|
|
m_bEnemyCrosshairVisible = bWantEnemyCrosshair;
|
|
|
|
float colorIndex = 99;
|
|
|
|
if ( !bWantEnemyCrosshair )
|
|
{
|
|
ConVarRef convar( "cl_crosshaircolor" );
|
|
colorIndex = convar.GetFloat();
|
|
}
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, colorIndex );
|
|
g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "onUpdateColor", args, 1 );
|
|
}
|
|
}
|
|
|
|
if ( iDesiredReticleMode != m_iReticleMode )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
ShowReticle( m_iReticleMode, false );
|
|
ShowReticle( iDesiredReticleMode, true );
|
|
m_iReticleMode = iDesiredReticleMode;
|
|
}
|
|
|
|
if ( m_iReticleMode == RETICLE_MODE_WEAPON )
|
|
{
|
|
float x = 0.0f;
|
|
float y = 0.0f;
|
|
|
|
#ifdef SIXENSE
|
|
if( g_pSixenseInput->IsEnabled() &&
|
|
C_BasePlayer::GetLocalPlayer() &&
|
|
( C_BasePlayer::GetLocalPlayer()->GetObserverMode()==OBS_MODE_NONE ) &&
|
|
lockMoveControllerRet.GetBool() == false )
|
|
#else
|
|
if ( inputsystem->MotionControllerActive() &&
|
|
C_BasePlayer::GetLocalPlayer() &&
|
|
( C_BasePlayer::GetLocalPlayer()->GetObserverMode()==OBS_MODE_NONE ) &&
|
|
lockMoveControllerRet.GetBool() == false )
|
|
#endif
|
|
{
|
|
|
|
Vector aimDirection;
|
|
|
|
if ( mc_use_recoil_on_cursor.GetBool())
|
|
{
|
|
AngleVectors(pCSPlayer->GetFinalAimAngle(), &aimDirection);
|
|
}
|
|
else
|
|
{
|
|
aimDirection = pCSPlayer->GetAimDirection();
|
|
}
|
|
|
|
Vector screen;
|
|
Vector point;
|
|
VectorAdd( CurrentViewOrigin(), aimDirection, point );
|
|
ScreenTransform( point, screen );
|
|
|
|
x = 0.5f * screen[0] * ScreenWidth() + 0.5f;
|
|
y = -0.5f * screen[1] * ScreenHeight() + 0.5f;
|
|
}
|
|
|
|
//0 = default
|
|
//1 = default static
|
|
//2 = classic standard
|
|
//3 = classic dynamic
|
|
//4 = classic static
|
|
if ( cl_crosshairstyle.GetInt() == 1 )
|
|
{
|
|
fDesiredFishtail = 0;
|
|
}
|
|
|
|
SetReticlePosition( iDesiredSpread, iDesiredGap, x, y, ( fDesiredFishtail / 200.0f ) * ( ScreenWidth() * 0.5f ) );
|
|
}
|
|
|
|
LockSlot( false, bSlotIsLocked );
|
|
}
|
|
|
|
void SFHudReticle::ToggleTeamEquipmentVisibility( bool bShow )
|
|
{
|
|
m_bForceShowAllTeammateTargetIDs = bShow;
|
|
|
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
|
{
|
|
CCSPlayer* pCSPlayer = ToCSPlayer( UTIL_PlayerByIndex( i ) );
|
|
|
|
FOR_EACH_VEC( m_playerIDs, j )
|
|
{
|
|
if ( m_playerIDs[ j ].hPlayer.Get( ) == pCSPlayer )
|
|
{
|
|
UpdatePlayerID( pCSPlayer, j );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SFHudReticle::AddNewPlayerID( CBaseEntity *player, bool bShowName, bool bFriend )
|
|
{
|
|
if ( !FlashAPIIsValid() )
|
|
return;
|
|
|
|
if ( !player || m_playerIDs.Count() >= MAX_PLAYER_NAME_ID_PANELS )
|
|
return;
|
|
|
|
SFVALUE newPanelHandle = NULL;
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
//Create new panel
|
|
newPanelHandle = m_pScaleformUI->Value_Invoke( m_FlashAPI, "AddNewPlayerID", NULL, 0 );
|
|
}
|
|
|
|
if ( newPanelHandle )
|
|
{
|
|
//Put the new panel in the list
|
|
PlayerIDPanel newPanel;
|
|
newPanel.hPlayer = player;
|
|
newPanel.panel = newPanelHandle;
|
|
newPanel.bActive = true;
|
|
newPanel.bFriend = bFriend;
|
|
newPanel.nHealth = player->GetHealth();
|
|
newPanel.nTeam = player->GetTeamNumber();
|
|
newPanel.flNameAlpha = 0;
|
|
newPanel.flLastHighlightTime = 0;
|
|
newPanel.bShowName = false;
|
|
newPanel.flUpdateAt = 0;
|
|
newPanel.iconsFlag = -1;
|
|
newPanel.bFlashedAmt = -1;// we will hide the panel immediately
|
|
|
|
if ( m_pScaleformUI->Value_GetType( newPanelHandle ) == IScaleformUI::VT_DisplayObject )
|
|
{
|
|
newPanel.arrowA = m_pScaleformUI->Value_GetMember( newPanelHandle, "IDArrow" );
|
|
newPanel.arrowB = m_pScaleformUI->Value_GetMember( newPanelHandle, "IDArrowBorder" );
|
|
newPanel.arrowF = m_pScaleformUI->Value_GetMember( newPanelHandle, "IDArrowFriend" );
|
|
newPanel.voiceIcon = m_pScaleformUI->Value_GetMember( newPanelHandle, "iconChat" );
|
|
newPanel.defuseIcon = m_pScaleformUI->Value_GetMember( newPanelHandle, "DefuseKitIcon" );
|
|
}
|
|
else
|
|
{
|
|
newPanel.arrowA = NULL;
|
|
newPanel.arrowB = NULL;
|
|
newPanel.arrowF = NULL;
|
|
newPanel.voiceIcon = NULL;
|
|
newPanel.defuseIcon = NULL;
|
|
}
|
|
|
|
m_playerIDs.AddToTail( newPanel );
|
|
|
|
UpdatePlayerID( player, m_playerIDs.Count()-1 );
|
|
}
|
|
}
|
|
|
|
void SFHudReticle::UpdatePlayerID( CBaseEntity *player, int slot, bool bHealthAndNameOnly )
|
|
{
|
|
if ( !FlashAPIIsValid() )
|
|
return;
|
|
|
|
C_CSPlayer *pCSPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
|
|
if ( !pCSPlayer || !player || m_playerIDs.Count() >= MAX_PLAYER_NAME_ID_PANELS || slot >= m_playerIDs.Count() )
|
|
return;
|
|
|
|
bool bDidSetName = false;
|
|
|
|
if ( !m_playerIDs[slot].panel )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but m_playerIDs[slot].panel is null!!\n" );
|
|
return;
|
|
}
|
|
|
|
C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
|
|
|
|
if ( !bHealthAndNameOnly )
|
|
{
|
|
int playerIndex = 0;
|
|
for ( int i = 0; i <= MAX_PLAYERS; i++ )
|
|
{
|
|
CBasePlayer* pCheckPlayer = UTIL_PlayerByIndex( i );
|
|
if ( pCheckPlayer && pCheckPlayer == player )
|
|
playerIndex = i;
|
|
}
|
|
|
|
int nColorID = -1;
|
|
if ( cs_PR && pCSPlayer->ShouldShowTeamPlayerColors( player->GetTeamNumber() ) )
|
|
nColorID = cs_PR->GetCompTeammateColor( playerIndex );
|
|
|
|
// set the color of the icon, need to do it by calling the script
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 4 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[slot].panel );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 1, m_playerIDs[slot].nTeam );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 2, m_playerIDs[slot].bFriend );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 3, nColorID );
|
|
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setIDTeamColor", args, 4 );
|
|
}
|
|
}
|
|
|
|
if ( !cs_PR )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but C_CS_PlayerResource is null!!\n" );
|
|
return;
|
|
}
|
|
|
|
SFVALUE animatedID = m_pScaleformUI->Value_GetMember( m_playerIDs[slot].panel, "IDClip" );
|
|
SFVALUE textBG = m_pScaleformUI->Value_GetMember( m_playerIDs[slot].panel, "IDTextBG" );
|
|
|
|
if ( !animatedID /*&& animatedIDDrop*/ || !textBG )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDClip and IDTextBG objects are null!!\n" );
|
|
return;
|
|
}
|
|
|
|
SFVALUE textmovie = m_pScaleformUI->Value_GetMember( animatedID, "IDTextMovie" );
|
|
|
|
if ( !textmovie /*&& textDrop*/ )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDTextMovie object is null!!\n" );
|
|
return;
|
|
}
|
|
|
|
SFVALUE text = m_pScaleformUI->Value_GetMember( textmovie, "IDText" );
|
|
|
|
if ( !text /*&& textDrop*/ )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDText object is null!!\n" );
|
|
return;
|
|
}
|
|
|
|
//IDWeaponTextParent
|
|
SFVALUE wepIconParent = m_pScaleformUI->Value_GetMember( textmovie, "IDWeaponTextParent" );
|
|
|
|
if ( !wepIconParent )
|
|
return;
|
|
|
|
SFVALUE wepIcons = m_pScaleformUI->Value_GetMember( wepIconParent, "IDWeaponText" );
|
|
if ( !wepIcons )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDWeaponText object is null!!\n" );
|
|
return;
|
|
}
|
|
|
|
wchar_t wszHealthText[ 10 ];
|
|
float flHealth = 0.0f;
|
|
|
|
C_CSPlayer *pTargetPlayer = static_cast<C_CSPlayer*>( player );
|
|
|
|
bool bLocalIsSpectatorViewer = CanSeeSpectatorOnlyTools();
|
|
|
|
bool bShowMoneyInsteadOfHealth = CSGameRules( )->CanSpendMoneyInMap( ) && CSGameRules( )->IsFreezePeriod( ) && !bLocalIsSpectatorViewer;
|
|
|
|
if ( bShowMoneyInsteadOfHealth ) // we show money in the place of health during freeze time
|
|
flHealth = pTargetPlayer->GetAccount( );
|
|
else
|
|
flHealth = ( MAX( 0.0f, ( float ) player->GetHealth( ) ) / ( float ) player->GetMaxHealth( ) );
|
|
|
|
|
|
// show the main equipped weapon, grenades and money during freezetime or if ShouldShowAllFriendlyEquipment
|
|
|
|
if ( ( !bLocalIsSpectatorViewer && ( CSGameRules( )->IsFreezePeriod( ) ) || ShouldShowAllFriendlyEquipment() ) )
|
|
{
|
|
CHudWeaponSelection *pHudSelection = (CHudWeaponSelection *)GET_HUDELEMENT( CHudWeaponSelection );
|
|
if ( !pHudSelection )
|
|
return;
|
|
|
|
wchar_t wszWeaponIcons[ MAX_DECORATED_PLAYER_NAME_LENGTH ] = { L"" };
|
|
|
|
// weapons are only shown in freeze time.
|
|
bool bShowWeapons = CSGameRules( )->IsFreezePeriod( ) || ShouldShowAllFriendlyEquipment();
|
|
bool bShowDefuser = ShouldShowAllFriendlyEquipment();
|
|
bool bShowC4 = ShouldShowAllFriendlyEquipment();
|
|
|
|
CSWeaponID nPrimaryWeaponID = WEAPON_KNIFE;
|
|
|
|
if ( bShowWeapons )
|
|
{
|
|
if ( pTargetPlayer && pTargetPlayer->GetActiveCSWeapon( ) )
|
|
{
|
|
if ( !IsPrimaryWeapon( nPrimaryWeaponID )/* && CSGameRules()->IsFreezePeriod()*/ )
|
|
{
|
|
// While in the freeze period we want to show their primary weapon if they have one
|
|
for ( int i = 0; i < MAX_WEAPONS; i++ )
|
|
{
|
|
C_WeaponCSBase *pWeapon = assert_cast< C_WeaponCSBase* >( pTargetPlayer->GetWeapon( i ) );
|
|
if ( !pWeapon )
|
|
continue;
|
|
|
|
CSWeaponID nIDTemp = pWeapon->GetCSWeaponID( );
|
|
if ( IsPrimaryWeapon( nIDTemp ) )
|
|
{
|
|
// Found a primary
|
|
nPrimaryWeaponID = nIDTemp;
|
|
break;
|
|
}
|
|
else if ( IsSecondaryWeapon( nIDTemp ) )
|
|
{
|
|
// Fall back to secondary if non-primary and non-secondary is active
|
|
nPrimaryWeaponID = nIDTemp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// let's wait on showing armor and defuse kits
|
|
// int nArmor = cs_PR->GetArmor( pTargetPlayer->entindex() );
|
|
// bool bHasHelmet = cs_PR->HasHelmet( pTargetPlayer->entindex() );
|
|
//
|
|
// if ( nArmor > 0 )
|
|
// {
|
|
// const char *szWeapon = "armor";
|
|
// if ( bHasHelmet )
|
|
// szWeapon = "armor_helmet";
|
|
//
|
|
// wchar_t wszWeapon[64];
|
|
// V_UTF8ToUnicode( szWeapon, wszWeapon, sizeof( wszWeapon ) );
|
|
// wchar_t szWeaponHTML[64];
|
|
// GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
|
|
// Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
|
|
// }
|
|
//
|
|
if ( bShowDefuser )
|
|
{
|
|
bool bHasDef = cs_PR->HasDefuser( pTargetPlayer->entindex( ) );
|
|
|
|
if ( bHasDef )
|
|
{
|
|
wchar_t wszWeapon[ 64 ];
|
|
V_UTF8ToUnicode( "defuser", wszWeapon, sizeof( wszWeapon ) );
|
|
wchar_t szWeaponHTML[ 64 ];
|
|
GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
|
|
Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
|
|
}
|
|
}
|
|
|
|
if ( bShowC4 )
|
|
{
|
|
bool bHasC4 = cs_PR->HasC4( pTargetPlayer->entindex( ) );
|
|
|
|
if ( bHasC4 )
|
|
{
|
|
wchar_t wszWeapon[ 64 ];
|
|
V_UTF8ToUnicode( "bomb-holder", wszWeapon, sizeof( wszWeapon ) );
|
|
wchar_t szWeaponHTML[ 64 ];
|
|
GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
|
|
Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
|
|
}
|
|
}
|
|
|
|
for ( int slot = MAX_WEAPON_SLOTS; slot >= 0; slot-- )
|
|
{
|
|
for ( int pos = MAX_WEAPON_POSITIONS; pos >= 0; pos-- )
|
|
{
|
|
C_WeaponCSBase *pWeapon = assert_cast< C_WeaponCSBase* >( pHudSelection->GetWeaponInSlotForTarget( pTargetPlayer, slot, pos ) );
|
|
// if we dont have a weapon OR if the found weapon is our selected weapon, skip it
|
|
|
|
if ( !pWeapon )
|
|
continue;
|
|
|
|
// if we're not showing weapons ignore anything that isn't utility
|
|
if ( !bShowWeapons && !pWeapon->IsKindOf( WEAPONTYPE_GRENADE ) )
|
|
{
|
|
continue;
|
|
}
|
|
// if we are showing weapons then we're only showing primary or utility
|
|
else if ( pWeapon->GetCSWeaponID( ) == nPrimaryWeaponID || pWeapon->IsKindOf( WEAPONTYPE_GRENADE ) )
|
|
{
|
|
CEconItemView *pItem = pWeapon->GetEconItemView( );
|
|
|
|
const char *szWeapon = ( ( pItem && pItem->IsValid() && pItem->GetItemIndex() && pItem->GetItemDefinition() )
|
|
? pItem->GetItemDefinition( )->GetDefinitionName( )
|
|
: pWeapon->GetClassname( ) );
|
|
|
|
if ( IsWeaponClassname( szWeapon ) )
|
|
{
|
|
szWeapon += WEAPON_CLASSNAME_PREFIX_LENGTH;
|
|
}
|
|
|
|
if ( Q_strcmp( "knife", szWeapon ) == 0 )
|
|
{
|
|
if ( pTargetPlayer && pTargetPlayer->GetTeamNumber( ) == TEAM_CT )
|
|
{
|
|
szWeapon = "knife_default_ct";
|
|
}
|
|
else
|
|
{
|
|
szWeapon = "knife_default_t";
|
|
}
|
|
}
|
|
|
|
wchar_t wszWeapon[ 64 ];
|
|
V_UTF8ToUnicode( szWeapon, wszWeapon, sizeof( wszWeapon ) );
|
|
|
|
wchar_t szWeaponHTML[ 64 ];
|
|
GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
|
|
|
|
int nCount = 1;
|
|
if ( pWeapon->IsKindOf( WEAPONTYPE_GRENADE ) )
|
|
nCount = pWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
|
|
|
|
for ( int nGren = 0; nGren < nCount; nGren++ )
|
|
{
|
|
Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pScaleformUI->Value_SetTextHTML( wepIcons, wszWeaponIcons );
|
|
}
|
|
else
|
|
{
|
|
m_pScaleformUI->Value_SetTextHTML( wepIcons, "" );
|
|
}
|
|
|
|
// bool bIsFullyBlinded = pCSPlayer->m_flFlashOverlayAlpha >= 180.0f;
|
|
// bool bIsFlashed = pCSPlayer->m_flFlashBangTime > ( gpGlobals->curtime + 0.5 );
|
|
if ( pTargetPlayer )
|
|
{
|
|
float flFlashFrac = 1.0 - clamp( pTargetPlayer->m_flFlashOverlayAlpha / 150, 0, 1 );
|
|
if ( pTargetPlayer->m_flFlashOverlayAlpha > 0 )
|
|
m_playerIDs[ slot ].bFlashedAmt = pTargetPlayer->m_flFlashOverlayAlpha;
|
|
|
|
if ( m_playerIDs[ slot ].bFlashedAmt != 0 )
|
|
{
|
|
if ( pTargetPlayer->m_flFlashOverlayAlpha <= 0 || m_playerIDs[ slot ].bFlashedAmt == -1 )
|
|
{
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[ slot ].panel );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hideFlashIcon", args, 1 );
|
|
}
|
|
m_playerIDs[ slot ].bFlashedAmt = 0;
|
|
}
|
|
else if ( CanSeeSpectatorOnlyTools( ) )
|
|
{
|
|
// show flashed
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[ slot ].panel );
|
|
m_pScaleformUI->ValueArray_SetElement( args, 1, flFlashFrac );
|
|
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setFlashIcon", args, 2 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
wchar_t wcNewString[ TEXTFIELD_LENGTH ];
|
|
wchar_t wszPlayerName[ MAX_DECORATED_PLAYER_NAME_LENGTH ];
|
|
|
|
const char *printFormatString = "#SFUIHUD_playerid_specteam";
|
|
// if ( pCSPlayer->ShouldShowTeamPlayerColors( player->GetTeamNumber() ) )
|
|
// {
|
|
// if ( bShowOverheadWeapons && CSGameRules()->CanSpendMoneyInMap() )
|
|
// printFormatString = "#SFUIHUD_playerid_overhead_money";
|
|
// else if ( flHealth < 0.25f )
|
|
// printFormatString = "#SFUIHUD_playerid_overhead_lowhealth";
|
|
// else
|
|
// printFormatString = "#SFUIHUD_playerid_overhead";
|
|
// }
|
|
// else if ( m_playerIDs[slot].nTeam == TEAM_CT )
|
|
if ( m_playerIDs[slot].nTeam == TEAM_CT )
|
|
{
|
|
if ( bShowMoneyInsteadOfHealth )
|
|
printFormatString = "#SFUIHUD_playerid_overhead_ct_money";
|
|
else if ( flHealth < 0.25f )
|
|
printFormatString = "#SFUIHUD_playerid_overhead_ct_lowhealth";
|
|
else
|
|
printFormatString = "#SFUIHUD_playerid_overhead_ct";
|
|
}
|
|
else
|
|
{
|
|
if ( bShowMoneyInsteadOfHealth )
|
|
printFormatString = "#SFUIHUD_playerid_overhead_t_money";
|
|
else if ( flHealth < 0.25f )
|
|
printFormatString = "#SFUIHUD_playerid_overhead_t_lowhealth";
|
|
else
|
|
printFormatString = "#SFUIHUD_playerid_overhead_t";
|
|
}
|
|
|
|
if ( printFormatString )
|
|
{
|
|
if ( bShowMoneyInsteadOfHealth )
|
|
{
|
|
V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"$%d", (int)flHealth );
|
|
}
|
|
else
|
|
{
|
|
V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"%.0f%%", flHealth * 100 );
|
|
}
|
|
|
|
wszHealthText[ ARRAYSIZE( wszHealthText )-1 ] = '\0';
|
|
|
|
cs_PR->GetDecoratedPlayerName( player->entindex(), wszPlayerName, sizeof( wszPlayerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
|
|
|
|
g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 2, wszPlayerName, wszHealthText );
|
|
}
|
|
|
|
m_pScaleformUI->Value_SetTextHTML( text, wcNewString );
|
|
|
|
bool bSetVisible = ShouldShowAllFriendlyEquipment() || m_playerIDs[ slot ].bShowName || m_playerIDs[ slot ].flLastHighlightTime == 0;
|
|
|
|
ScaleformDisplayInfo dinfo;
|
|
ScaleformDisplayInfo dinfo2;
|
|
m_pScaleformUI->Value_GetDisplayInfo( textmovie, &dinfo );
|
|
m_pScaleformUI->Value_GetDisplayInfo( textBG, &dinfo2 );
|
|
|
|
bool bShowAllNamesForSpec = ( bLocalIsSpectatorViewer && spec_show_xray.GetInt() );
|
|
float flMaxDrawDist = bShowAllNamesForSpec ? cl_teamid_overhead_maxdist_spec.GetInt() : cl_teamid_overhead_maxdist.GetInt();
|
|
|
|
Vector vecOtherPlayerEyes = pTargetPlayer->EyePosition() + Vector( 0, 0, 3 );
|
|
Vector toAimSpot = vecOtherPlayerEyes - pCSPlayer->EyePosition();
|
|
float rangeToEnemy = toAimSpot.NormalizeInPlace();
|
|
|
|
|
|
float flAlp = RemapValClamped( rangeToEnemy,
|
|
500.0f, flMaxDrawDist,
|
|
100.0f, 50.0f );
|
|
|
|
m_playerIDs[ slot ].flNameAlpha = bLocalIsSpectatorViewer ? cl_teamid_overhead_name_alpha.GetInt() : flAlp;
|
|
|
|
|
|
dinfo.SetAlpha( m_playerIDs[slot].flNameAlpha );
|
|
dinfo2.SetAlpha( m_playerIDs[slot].flNameAlpha/7 );
|
|
dinfo.SetVisibility( bSetVisible );
|
|
dinfo2.SetVisibility( bSetVisible );
|
|
m_pScaleformUI->Value_SetDisplayInfo( textmovie, &dinfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( textBG, &dinfo2 );
|
|
|
|
bDidSetName = true;
|
|
}
|
|
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
SafeReleaseSFVALUE( wepIconParent );
|
|
SafeReleaseSFVALUE( wepIcons );
|
|
SafeReleaseSFVALUE( textmovie );
|
|
SafeReleaseSFVALUE( text );
|
|
|
|
WITH_SFVALUEARRAY( args, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[slot].panel );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "UpdateBGSize", args, 1 );
|
|
}
|
|
|
|
SafeReleaseSFVALUE( animatedID );
|
|
SafeReleaseSFVALUE( textBG );
|
|
}
|
|
|
|
if ( !bDidSetName )
|
|
{
|
|
Warning( "AddNewPlayerID called and updated in sfhudreticle, but no name was displayed!!!!\n" );
|
|
}
|
|
}
|
|
|
|
void SFHudReticle::GetIconHTML( const wchar_t * szIcon, wchar_t * szBuffer, int nBufferSize, bool bSelected )
|
|
{
|
|
if ( bSelected )
|
|
V_snwprintf( szBuffer, nBufferSize, HUDRET_WEPICON_SELECTED_IMG_STRING, szIcon );
|
|
else
|
|
V_snwprintf( szBuffer, nBufferSize, HUDRET_WEPICON_IMG_STRING, szIcon );
|
|
}
|
|
|
|
bool SFHudReticle::ShouldShowAllFriendlyTargetIDs( void )
|
|
{
|
|
extern ConVar sv_teamid_overhead_always_prohibit;
|
|
if ( sv_teamid_overhead_always_prohibit.GetBool() )
|
|
return false;
|
|
|
|
return ( m_bForceShowAllTeammateTargetIDs || cl_teamid_overhead_always.GetInt() >= 1 );
|
|
}
|
|
|
|
bool SFHudReticle::ShouldShowAllFriendlyEquipment( void )
|
|
{
|
|
extern ConVar sv_show_team_equipment_prohibit;
|
|
if ( sv_show_team_equipment_prohibit.GetBool() )
|
|
return false;
|
|
|
|
return ( m_bForceShowAllTeammateTargetIDs || cl_teamid_overhead_always.GetInt() == 2 );
|
|
}
|
|
|
|
bool SFHudReticle::SetReticlePosition( int distance, int crosshairGap, int offsetX, int offsetY, int nDesiredFishtail )
|
|
{
|
|
bool bMadeChanges = false;
|
|
bool bSlotIsLocked = false;
|
|
|
|
if ( m_WeaponCrosshairHandle )
|
|
{
|
|
ScaleformDisplayInfo dinfo;
|
|
|
|
LockSlot( true, bSlotIsLocked );
|
|
|
|
//0 = default
|
|
//1 = default static
|
|
//2 = classic standard
|
|
//3 = classic dynamic
|
|
//4 = classic static
|
|
if ( cl_crosshairstyle.GetInt() == 0 )
|
|
//if ( cl_dynamiccrosshair.GetBool() )
|
|
{
|
|
// setting this once here will make all of these become visible
|
|
dinfo.SetVisibility( true );
|
|
|
|
if ( m_crosshairDot )
|
|
{
|
|
ScaleformDisplayInfo dotDisplayInfo;
|
|
dotDisplayInfo.SetX( offsetX + m_dotX - nDesiredFishtail );
|
|
dotDisplayInfo.SetY( offsetY + m_dotY - nDesiredFishtail );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_crosshairDot, &dotDisplayInfo );
|
|
}
|
|
|
|
if ( m_blackRing )
|
|
{
|
|
ScaleformDisplayInfo blackRingDisplayInfo;
|
|
blackRingDisplayInfo.SetX( offsetX + m_blackRingX );
|
|
blackRingDisplayInfo.SetY( offsetY + m_blackRingY );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_blackRing, &blackRingDisplayInfo );
|
|
}
|
|
|
|
if ( m_FriendCrosshair )
|
|
{
|
|
ScaleformDisplayInfo friendlyCrossHairDisplayInfo;
|
|
friendlyCrossHairDisplayInfo.SetX( offsetX + m_friendIndicatorX - nDesiredFishtail );
|
|
friendlyCrossHairDisplayInfo.SetY( offsetY + m_friendIndicatorY - nDesiredFishtail );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_FriendCrosshair, &friendlyCrossHairDisplayInfo );
|
|
}
|
|
|
|
//Hide the arcs if we get the sentinel value as the desired distance
|
|
if ( distance == -1 )
|
|
{
|
|
ScaleformDisplayInfo hideArcsDisplayInfo;
|
|
hideArcsDisplayInfo.SetVisibility( false );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_topCrosshairArc, &hideArcsDisplayInfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_bottomCrosshairArc, &hideArcsDisplayInfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_leftCrosshairArc, &hideArcsDisplayInfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_rightCrosshairArc, &hideArcsDisplayInfo );
|
|
|
|
}
|
|
else
|
|
{
|
|
dinfo.SetX( offsetX - nDesiredFishtail );
|
|
dinfo.SetY( - distance + offsetY );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_topCrosshairArc, &dinfo );
|
|
|
|
dinfo.SetX( distance + offsetX - nDesiredFishtail );
|
|
dinfo.SetY( offsetY );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_rightCrosshairArc, &dinfo );
|
|
|
|
dinfo.SetX( - distance + offsetX - nDesiredFishtail );
|
|
dinfo.SetY( offsetY );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_leftCrosshairArc, &dinfo );
|
|
|
|
dinfo.SetX( offsetX - nDesiredFishtail );
|
|
dinfo.SetY( distance + offsetY );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_bottomCrosshairArc, &dinfo );
|
|
}
|
|
|
|
|
|
if ( crosshairGap == -1 )
|
|
{
|
|
ScaleformDisplayInfo hidePipsDisplayInfo;
|
|
hidePipsDisplayInfo.SetVisibility( false );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_TopPip, &hidePipsDisplayInfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_BottomPip, &hidePipsDisplayInfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_LeftPip, &hidePipsDisplayInfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_RightPip, &hidePipsDisplayInfo );
|
|
}
|
|
else
|
|
{
|
|
dinfo.SetX( offsetX - nDesiredFishtail );
|
|
dinfo.SetY( m_TopPipY - crosshairGap + offsetY);
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_TopPip, &dinfo );
|
|
|
|
dinfo.SetX( offsetX + 1 - nDesiredFishtail );
|
|
dinfo.SetY( m_BottomPipY + crosshairGap + offsetY+1);
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_BottomPip, &dinfo );
|
|
|
|
dinfo.SetY(offsetY+1);
|
|
dinfo.SetX( m_LeftPipX - crosshairGap + offsetX - nDesiredFishtail );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_LeftPip, &dinfo );
|
|
|
|
dinfo.SetY(offsetY);
|
|
dinfo.SetX( m_RightPipX + crosshairGap + offsetX + 1 - nDesiredFishtail );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_RightPip, &dinfo );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// make the arcs invisible
|
|
dinfo.SetVisibility( false );
|
|
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_topCrosshairArc, &dinfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_rightCrosshairArc, &dinfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_leftCrosshairArc, &dinfo );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_bottomCrosshairArc, &dinfo );
|
|
|
|
dinfo.SetVisibility( true );
|
|
|
|
float cg = cl_fixedcrosshairgap.GetFloat();
|
|
|
|
dinfo.SetX( offsetX - nDesiredFishtail );
|
|
dinfo.SetY( m_TopPipY - cg + offsetY);
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_TopPip, &dinfo );
|
|
|
|
dinfo.SetX( offsetX + 1 - nDesiredFishtail );
|
|
dinfo.SetY( m_BottomPipY + cg + offsetY+1);
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_BottomPip, &dinfo );
|
|
|
|
dinfo.SetY(offsetY+1);
|
|
dinfo.SetX( m_LeftPipX - cg + offsetX - nDesiredFishtail );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_LeftPip, &dinfo );
|
|
|
|
dinfo.SetY(offsetY);
|
|
dinfo.SetX( m_RightPipX + cg + offsetX + 1 - nDesiredFishtail );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_RightPip, &dinfo );
|
|
}
|
|
|
|
m_iLastSpread = distance;
|
|
m_iLastGap = crosshairGap;
|
|
bMadeChanges = true;
|
|
}
|
|
|
|
// Update the position of the text.
|
|
if ( m_bTextIDVisible && m_IDMovie && m_IDText )
|
|
{
|
|
LockSlot( true, bSlotIsLocked );
|
|
|
|
// text movie
|
|
ScaleformDisplayInfo displayInfo;
|
|
displayInfo.SetX( offsetX + m_IDMovieX );
|
|
displayInfo.SetY( offsetY + m_IDMovieY );
|
|
m_pScaleformUI->Value_SetDisplayInfo( m_IDMovie, &displayInfo );
|
|
|
|
bMadeChanges = true;
|
|
}
|
|
|
|
LockSlot( false, bSlotIsLocked );
|
|
|
|
return bMadeChanges;
|
|
}
|
|
|
|
|
|
void SFHudReticle::FlashReady( void )
|
|
{
|
|
m_ObserverCrosshairHandle = m_pScaleformUI->Value_GetMember( m_FlashAPI, "Observer" );
|
|
|
|
PerformSwapReticle( "Crosshair1" );
|
|
|
|
m_IDMovie = m_pScaleformUI->Value_GetMember( m_FlashAPI, "TargetID" );
|
|
|
|
if ( m_IDMovie )
|
|
{
|
|
SFVALUE animatedID = m_pScaleformUI->Value_GetMember( m_IDMovie, "IDAnimated" );
|
|
|
|
if ( animatedID )
|
|
{
|
|
m_IDText = m_pScaleformUI->Value_GetMember( animatedID, "TextBox" );
|
|
m_pScaleformUI->Value_SetTextHTML( m_IDText, " " );
|
|
SafeReleaseSFVALUE( animatedID );
|
|
}
|
|
}
|
|
|
|
m_FlashedIcon = m_pScaleformUI->Value_GetMember( m_FlashAPI, "FlashedBlind" );
|
|
// // Update the position of the text.
|
|
// if ( m_FlashedIcon )
|
|
// {
|
|
// LockSlot( true, bSlotIsLocked );
|
|
//
|
|
// // text movie
|
|
// ScaleformDisplayInfo displayInfo;
|
|
// m_pScaleformUI->Value_GetDisplayInfo( m_FlashedIcon, &displayInfo );
|
|
// displayInfo.SetX( offsetX + m_IDMovieX );
|
|
// displayInfo.SetY( offsetY + m_IDMovieY );
|
|
// m_pScaleformUI->Value_SetDisplayInfo( m_IDMovie, &displayInfo );
|
|
//
|
|
// bMadeChanges = true;
|
|
// }
|
|
|
|
ResetDisplay();
|
|
|
|
ListenForGameEvent( "item_pickup" );
|
|
ListenForGameEvent( "ammo_pickup" );
|
|
ListenForGameEvent( "player_death" );
|
|
ListenForGameEvent( "round_start" );
|
|
ListenForGameEvent( "round_end" );
|
|
ListenForGameEvent( "round_freeze_end" );
|
|
|
|
ListenForGameEvent( "bomb_planted" );
|
|
ListenForGameEvent( "defuser_pickup" );
|
|
ListenForGameEvent( "bomb_dropped" );
|
|
ListenForGameEvent( "bomb_pickup" );
|
|
ListenForGameEvent( "grenade_thrown" );
|
|
|
|
}
|
|
|
|
bool SFHudReticle::PreUnloadFlash( void )
|
|
{
|
|
SafeReleaseSFVALUE( m_WeaponCrosshairHandle );
|
|
SafeReleaseSFVALUE( m_ObserverCrosshairHandle );
|
|
|
|
SafeReleaseSFVALUE( m_TopPip );
|
|
SafeReleaseSFVALUE( m_BottomPip );
|
|
SafeReleaseSFVALUE( m_LeftPip );
|
|
SafeReleaseSFVALUE( m_RightPip );
|
|
|
|
SafeReleaseSFVALUE( m_topCrosshairArc );
|
|
SafeReleaseSFVALUE( m_rightCrosshairArc );
|
|
SafeReleaseSFVALUE( m_leftCrosshairArc );
|
|
SafeReleaseSFVALUE( m_bottomCrosshairArc );
|
|
|
|
SafeReleaseSFVALUE( m_FriendCrosshair );
|
|
SafeReleaseSFVALUE( m_crosshairDot );
|
|
SafeReleaseSFVALUE( m_blackRing );
|
|
|
|
|
|
SafeReleaseSFVALUE( m_IDMovie );
|
|
SafeReleaseSFVALUE( m_IDText );
|
|
|
|
SafeReleaseSFVALUE( m_FlashedIcon );
|
|
|
|
RemoveAllIDs();
|
|
|
|
return true;
|
|
}
|
|
|
|
void SFHudReticle::ResetDisplay( void )
|
|
{
|
|
|
|
// hide everything we don't want / need;
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
if ( m_IDMovie )
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "HideNow", NULL, 0 );
|
|
}
|
|
|
|
if ( m_FlashedIcon )
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
|
|
m_bFlashedIconFadingOut = false;
|
|
}
|
|
|
|
if ( m_FriendCrosshair )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, false );
|
|
}
|
|
|
|
ShowReticle( RETICLE_MODE_WEAPON, false );
|
|
ShowReticle( RETICLE_MODE_OBSERVER, false );
|
|
}
|
|
|
|
m_fIDTimer = 0;
|
|
m_bTextIDVisible = false;
|
|
m_bFriendlyCrosshairVisible = false;
|
|
|
|
m_iReticleMode = RETICLE_MODE_NONE;
|
|
|
|
RemoveAllIDs();
|
|
}
|
|
|
|
void SFHudReticle::LevelInit( void )
|
|
{
|
|
if ( !FlashAPIIsValid() )
|
|
{
|
|
SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudReticle, this, Reticle );
|
|
}
|
|
else
|
|
{
|
|
ResetDisplay();
|
|
}
|
|
}
|
|
|
|
void SFHudReticle::LevelShutdown( void )
|
|
{
|
|
if ( FlashAPIIsValid() )
|
|
{
|
|
RemoveFlashElement();
|
|
}
|
|
}
|
|
|
|
bool SFHudReticle::ShouldDraw( void )
|
|
{
|
|
if ( IsTakingAFreezecamScreenshot() )
|
|
return false;
|
|
|
|
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
|
|
if ( !pPlayer )
|
|
return false;
|
|
|
|
if ( pPlayer->GetObserverInterpState() == C_CSPlayer::OBSERVER_INTERP_TRAVELING )
|
|
return false;
|
|
|
|
bool bNeedsDraw = false;
|
|
if ( (pPlayer->GetObserverMode() == OBS_MODE_ROAMING) || (pPlayer->GetObserverMode() == OBS_MODE_FIXED) )
|
|
bNeedsDraw = true;
|
|
|
|
return cl_drawhud.GetBool() && (bNeedsDraw || CHudElement::ShouldDraw());
|
|
}
|
|
|
|
|
|
void SFHudReticle::SetActive( bool bActive )
|
|
{
|
|
if ( !FlashAPIIsValid() )
|
|
return;
|
|
|
|
SF_SPLITSCREEN_PLAYER_GUARD();
|
|
|
|
if ( !bActive && m_bActive )
|
|
{
|
|
ResetDisplay();
|
|
}
|
|
else if ( bActive && !m_bActive )
|
|
{
|
|
SplitScreenSlottedConVarRef convar( GET_ACTIVE_SPLITSCREEN_SLOT(), "cl_crosshaircolor" );
|
|
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
|
|
{
|
|
g_pScaleformUI->ValueArray_SetElement( args, 0, convar.GetFloat() );
|
|
g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "onUpdateColor", args, 1 );
|
|
}
|
|
}
|
|
|
|
CHudElement::SetActive( bActive );
|
|
}
|
|
|
|
void SFHudReticle::OnSwapReticle( SCALEFORM_CALLBACK_ARGS_DECL )
|
|
{
|
|
SF_SPLITSCREEN_PLAYER_GUARD();
|
|
PerformSwapReticle( m_pScaleformUI->Params_GetArgAsString( obj, 0 ) );
|
|
}
|
|
|
|
void SFHudReticle::PerformSwapReticle( const char * szReticleName )
|
|
{
|
|
SafeReleaseSFVALUE( m_WeaponCrosshairHandle );
|
|
SafeReleaseSFVALUE( m_FriendCrosshair );
|
|
SafeReleaseSFVALUE( m_crosshairDot );
|
|
SafeReleaseSFVALUE( m_blackRing );
|
|
SafeReleaseSFVALUE( m_TopPip );
|
|
SafeReleaseSFVALUE( m_BottomPip );
|
|
SafeReleaseSFVALUE( m_LeftPip );
|
|
SafeReleaseSFVALUE( m_RightPip );
|
|
SafeReleaseSFVALUE( m_topCrosshairArc );
|
|
SafeReleaseSFVALUE( m_rightCrosshairArc );
|
|
SafeReleaseSFVALUE( m_leftCrosshairArc );
|
|
SafeReleaseSFVALUE( m_bottomCrosshairArc );
|
|
|
|
m_WeaponCrosshairHandle = m_pScaleformUI->Value_GetMember( m_FlashAPI, szReticleName );
|
|
|
|
if ( m_WeaponCrosshairHandle )
|
|
{
|
|
ScaleformDisplayInfo dinfo;
|
|
|
|
m_FriendCrosshair = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "FriendCrosshair" );
|
|
m_crosshairDot = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "Dot" );
|
|
m_blackRing = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "BlackRing" );
|
|
|
|
if ( !m_bCrosshairPositionsInitialized )
|
|
{
|
|
m_bCrosshairPositionsInitialized = true;
|
|
|
|
if ( m_FriendCrosshair )
|
|
{
|
|
m_pScaleformUI->Value_GetDisplayInfo( m_FriendCrosshair, &dinfo );
|
|
m_friendIndicatorX = dinfo.GetX();
|
|
m_friendIndicatorY = dinfo.GetY();
|
|
}
|
|
|
|
if ( m_crosshairDot )
|
|
{
|
|
m_pScaleformUI->Value_GetDisplayInfo( m_crosshairDot, &dinfo );
|
|
m_dotX = dinfo.GetX();
|
|
m_dotY = dinfo.GetY();
|
|
}
|
|
|
|
if ( m_blackRing )
|
|
{
|
|
m_pScaleformUI->Value_GetDisplayInfo( m_blackRing, &dinfo );
|
|
m_blackRingX = dinfo.GetX();
|
|
m_blackRingY = dinfo.GetY();
|
|
}
|
|
|
|
}
|
|
|
|
m_TopPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "TopPip" );
|
|
if ( m_TopPip )
|
|
{
|
|
m_TopPipY = 0;
|
|
}
|
|
|
|
m_BottomPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "BottomPip" );
|
|
if ( m_BottomPip )
|
|
{
|
|
m_BottomPipY = 0;
|
|
}
|
|
|
|
m_LeftPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "LeftPip" );
|
|
if ( m_LeftPip )
|
|
{
|
|
m_LeftPipX = 0;
|
|
}
|
|
|
|
m_RightPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "RightPip" );
|
|
if ( m_RightPip )
|
|
{
|
|
m_RightPipX = 0;
|
|
}
|
|
|
|
m_topCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "TopArc" );
|
|
m_rightCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "RightArc" );
|
|
m_leftCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "LeftArc" );
|
|
m_bottomCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "BottomArc" );
|
|
}
|
|
|
|
if ( m_FriendCrosshair )
|
|
{
|
|
m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, false );
|
|
}
|
|
|
|
if ( m_IDMovie )
|
|
{
|
|
ScaleformDisplayInfo dinfo;
|
|
m_pScaleformUI->Value_GetDisplayInfo( m_IDMovie, &dinfo );
|
|
m_IDMovieX = dinfo.GetX();
|
|
m_IDMovieY = dinfo.GetY();
|
|
}
|
|
|
|
// set these here because the flash code makes them invisible
|
|
m_bFriendlyCrosshairVisible = false;
|
|
m_iReticleMode = RETICLE_MODE_NONE;
|
|
|
|
m_iLastSpread = -1;
|
|
m_iLastGap = -1;
|
|
}
|
|
|
|
void SFHudReticle::RemoveID( int index )
|
|
{
|
|
SFVALUE panel = m_playerIDs[ index ].panel;
|
|
SafeReleaseSFVALUE( m_playerIDs[ index ].arrowA );
|
|
SafeReleaseSFVALUE( m_playerIDs[ index ].arrowB );
|
|
SafeReleaseSFVALUE( m_playerIDs[ index ].arrowF );
|
|
SafeReleaseSFVALUE( m_playerIDs[ index ].voiceIcon );
|
|
SafeReleaseSFVALUE( m_playerIDs[ index ].defuseIcon );
|
|
m_playerIDs.Remove( index );
|
|
WITH_SFVALUEARRAY_SLOT_LOCKED( data, 1 )
|
|
{
|
|
m_pScaleformUI->ValueArray_SetElement( data, 0, panel );
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "RemovePlayerID", data, 1 );
|
|
}
|
|
SafeReleaseSFVALUE( panel );
|
|
}
|
|
|
|
void SFHudReticle::RemoveAllIDs( void )
|
|
{
|
|
if ( m_pScaleformUI )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
//Remove all items before we exit
|
|
while( m_playerIDs.Count() > 0 )
|
|
{
|
|
RemoveID( 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFHudReticle::FireGameEvent( IGameEvent *event )
|
|
{
|
|
const char *type = event->GetName();
|
|
|
|
int nUserId = event->GetInt( "userid" );
|
|
C_BasePlayer *pPlayer = UTIL_PlayerByUserId( nUserId );
|
|
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
|
|
if ( !V_strcmp( type, "player_death" ) )
|
|
{
|
|
// if we were the one that died or the player we are spectating, remove all the stuff!
|
|
if ( pPlayer && (pPlayer->entindex() == pLocalPlayer->entindex() || (pLocalPlayer->GetObserverTarget() && pPlayer == pLocalPlayer->GetObserverTarget())) )
|
|
{
|
|
RemoveAllIDs();
|
|
|
|
if ( m_IDMovie )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "HideNow", NULL, 0 );
|
|
}
|
|
}
|
|
|
|
if ( m_FlashedIcon )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
|
|
m_bFlashedIconFadingOut = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( !V_strcmp( type, "round_end" ) )
|
|
{
|
|
RemoveAllIDs();
|
|
}
|
|
else if ( !V_strcmp( type, "round_start" ) )
|
|
{
|
|
RemoveAllIDs();
|
|
|
|
if ( m_IDMovie && FlashAPIIsValid() )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "HideNow", NULL, 0 );
|
|
}
|
|
}
|
|
|
|
if ( m_FlashedIcon )
|
|
{
|
|
WITH_SLOT_LOCKED
|
|
{
|
|
m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
|
|
m_bFlashedIconFadingOut = false;
|
|
}
|
|
}
|
|
}
|
|
else if ( !V_strcmp( type, "item_pickup" ) ||
|
|
!V_strcmp( type, "ammo_pickup" ) ||
|
|
!V_strcmp( type, "bomb_planted" ) ||
|
|
!V_strcmp( type, "defuser_pickup" ) ||
|
|
!V_strcmp( type, "bomb_dropped" ) ||
|
|
!V_strcmp( type, "bomb_pickup" ) ||
|
|
!V_strcmp( type, "grenade_thrown" ) )
|
|
{
|
|
if ( pLocalPlayer )
|
|
{
|
|
FOR_EACH_VEC( m_playerIDs, j )
|
|
{
|
|
if ( m_playerIDs[j].hPlayer.Get() == pPlayer )
|
|
{
|
|
m_playerIDs[j].flUpdateAt = (gpGlobals->curtime + 0.1f);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( !V_strcmp( type, "round_freeze_end" ) )
|
|
{
|
|
if ( pLocalPlayer )
|
|
{
|
|
FOR_EACH_VEC( m_playerIDs, j )
|
|
{
|
|
m_playerIDs[j].flUpdateAt = (gpGlobals->curtime + 0.1f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|