mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
add hl1,portal,dod source code
This commit is contained in:
@@ -0,0 +1,942 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Draws DoD:S's death notices
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "hudelement.h"
|
||||
#include "hud_macros.h"
|
||||
#include "c_playerresource.h"
|
||||
#include "iclientmode.h"
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <KeyValues.h>
|
||||
#include "c_baseplayer.h"
|
||||
#include "c_team.h"
|
||||
|
||||
#include "dod_shareddefs.h"
|
||||
#include "clientmode_dod.h"
|
||||
#include "c_dod_player.h"
|
||||
#include "c_dod_playerresource.h"
|
||||
#include "c_dod_objective_resource.h"
|
||||
#include "dod_hud_freezepanel.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
ConVar hud_deathnotice_time( "hud_deathnotice_time", "6", 0 );
|
||||
ConVar cl_deathicon_width( "cl_deathicon_width", "57" );
|
||||
ConVar cl_deathicon_height( "cl_deathicon_height", "18" );
|
||||
|
||||
#define MAX_DEATHNOTICE_NAME_LENGTH 128 // to hold multiple player cappers
|
||||
|
||||
// a very useful function for getting the ideal scale factor of a sprite that's to be
|
||||
// scaled into a space
|
||||
float GetScale( int nIconWidth, int nIconHeight, int nWidth, int nHeight );
|
||||
|
||||
// Player entries in a death notice
|
||||
struct DeathNoticePlayer
|
||||
{
|
||||
char szName[MAX_DEATHNOTICE_NAME_LENGTH];
|
||||
int iEntIndex;
|
||||
};
|
||||
|
||||
// Contents of each entry in our list of death notices
|
||||
struct DeathNoticeItem
|
||||
{
|
||||
DeathNoticeItem()
|
||||
{
|
||||
iconDeath = NULL;
|
||||
bSuicide = false;
|
||||
bCapMsg = false;
|
||||
bLocalPlayerInvolved = false;
|
||||
bDefense = false;
|
||||
bDominating = false;
|
||||
}
|
||||
|
||||
DeathNoticePlayer Killer;
|
||||
DeathNoticePlayer Victim;
|
||||
CHudTexture *iconDeath;
|
||||
bool bSuicide;
|
||||
float flDisplayTime;
|
||||
|
||||
// When I see a boolean like this, I know serious bullshit is afoot!
|
||||
bool bCapMsg; // if this is set, this is a flag cap msg.
|
||||
// Killer.szName is the list of players that capped
|
||||
// Victim.szName is the localized point name
|
||||
// iMaterial is the material index of the flag icon to show
|
||||
// iEntIndex in Killer is the capping team
|
||||
|
||||
|
||||
int iMaterial;
|
||||
|
||||
bool bLocalPlayerInvolved; // Is the local player a capper, killer or victim in this message
|
||||
|
||||
bool bDefense;
|
||||
|
||||
bool bDominating;
|
||||
wchar_t wzInfoText[32]; // any additional text to display next to icon
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHudDeathNotice : public CHudElement, public vgui::Panel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CHudDeathNotice, vgui::Panel );
|
||||
public:
|
||||
CHudDeathNotice( const char *pElementName );
|
||||
|
||||
void Init( void );
|
||||
void VidInit( void );
|
||||
virtual bool ShouldDraw( void );
|
||||
virtual void Paint( void );
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *scheme );
|
||||
|
||||
void SetColorForNoticePlayer( int iTeamNumber );
|
||||
void RetireExpiredDeathNotices( void );
|
||||
|
||||
void FireGameEvent( IGameEvent * event);
|
||||
|
||||
void DrawBackgroundBox( int x, int y, int w, int h, bool bLocalPlayerInvolved );
|
||||
|
||||
int DrawDefenseItem( DeathNoticeItem *pItem, int xRight, int y );
|
||||
int DrawDeathNoticeItem( DeathNoticeItem *pItem, int x, int y );
|
||||
int DrawDominationNoticeItem( DeathNoticeItem *pItem, int xRight, int y );
|
||||
|
||||
virtual bool IsVisible( void );
|
||||
|
||||
void AddAdditionalMsg( int iKillerID, int iVictimID, const char *pMsgKey );
|
||||
|
||||
void PlayRivalrySounds( int iKillerIndex, int iVictimIndex, int iType );
|
||||
|
||||
private:
|
||||
|
||||
CPanelAnimationVarAliasType( float, m_flLineHeight, "LineHeight", "15", "proportional_float" );
|
||||
|
||||
CPanelAnimationVar( float, m_flMaxDeathNotices, "MaxDeathNotices", "4" );
|
||||
|
||||
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudNumbersTimer" );
|
||||
|
||||
CPanelAnimationVar( Color, m_BackgroundColor, "BackgroundColor", "255 255 255 100" );
|
||||
CPanelAnimationVar( Color, m_ActiveBackgroundColor, "ActiveBackgroundColor", "255 255 255 140" );
|
||||
|
||||
// Special death notice icons
|
||||
CHudTexture *m_iconD_skull;
|
||||
CHudTexture *m_pIconDefended;
|
||||
CHudTexture *m_iconDomination;
|
||||
|
||||
CUtlVector<DeathNoticeItem> m_DeathNotices;
|
||||
|
||||
int m_iMaterialTexture;
|
||||
};
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
DECLARE_HUDELEMENT( CHudDeathNotice );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CHudDeathNotice::CHudDeathNotice( const char *pElementName ) :
|
||||
CHudElement( pElementName ), BaseClass( NULL, "HudDeathNotice" )
|
||||
{
|
||||
vgui::Panel *pParent = g_pClientMode->GetViewport();
|
||||
SetParent( pParent );
|
||||
|
||||
m_iconD_skull = NULL;
|
||||
m_iconDomination = NULL;
|
||||
|
||||
SetHiddenBits( HIDEHUD_MISCSTATUS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::ApplySchemeSettings( IScheme *scheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( scheme );
|
||||
SetPaintBackgroundEnabled( false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::Init( void )
|
||||
{
|
||||
ListenForGameEvent( "player_death" );
|
||||
ListenForGameEvent( "dod_point_captured" );
|
||||
ListenForGameEvent( "dod_capture_blocked" );
|
||||
|
||||
m_iMaterialTexture = vgui::surface()->CreateNewTextureID();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::VidInit( void )
|
||||
{
|
||||
m_iconD_skull = gHUD.GetIcon( "d_skull_dod" );
|
||||
m_pIconDefended = gHUD.GetIcon( "icon_defended" );
|
||||
m_iconDomination = gHUD.GetIcon( "leaderboard_dominated" );
|
||||
m_DeathNotices.Purge();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draw if we've got at least one death notice in the queue
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudDeathNotice::ShouldDraw( void )
|
||||
{
|
||||
return ( CHudElement::ShouldDraw() && ( m_DeathNotices.Count() ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Hide if we just took a freezecam screenshot
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudDeathNotice::IsVisible( void )
|
||||
{
|
||||
if ( IsTakingAFreezecamScreenshot() )
|
||||
return false;
|
||||
|
||||
return BaseClass::IsVisible();
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::SetColorForNoticePlayer( int iTeamNumber )
|
||||
{
|
||||
Color c = g_PR->GetTeamColor( iTeamNumber );
|
||||
surface()->DrawSetTextColor( c );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::Paint()
|
||||
{
|
||||
int yStart = GetClientModeDODNormal()->GetDeathMessageStartHeight();
|
||||
|
||||
surface()->DrawSetTextFont( m_hTextFont );
|
||||
|
||||
int y = yStart;
|
||||
int x = GetWide();
|
||||
|
||||
int iCount = m_DeathNotices.Count();
|
||||
for ( int i = 0; i < iCount; i++ )
|
||||
{
|
||||
if ( m_DeathNotices[i].bDefense )
|
||||
y += DrawDefenseItem( &m_DeathNotices[i], x, y );
|
||||
else
|
||||
y += DrawDeathNoticeItem( &m_DeathNotices[i], x, y );
|
||||
}
|
||||
|
||||
// Now retire any death notices that have expired
|
||||
RetireExpiredDeathNotices();
|
||||
}
|
||||
|
||||
int CHudDeathNotice::DrawDefenseItem( DeathNoticeItem *pItem, int xRight, int y )
|
||||
{
|
||||
// Get the team numbers for the players involved
|
||||
int iKillerTeam = pItem->Killer.iEntIndex;
|
||||
int iVictimTeam = TEAM_UNASSIGNED;
|
||||
|
||||
wchar_t victim[ 256 ];
|
||||
wchar_t killer[ 256 ];
|
||||
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->Victim.szName, victim, sizeof( victim ) );
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->Killer.szName, killer, sizeof( killer ) );
|
||||
|
||||
// Get the local position for this notice
|
||||
int len = UTIL_ComputeStringWidth( m_hTextFont, victim );
|
||||
|
||||
int iconWide;
|
||||
int iconTall;
|
||||
|
||||
float scale = ( (float)ScreenHeight() / 480.0f ) * 0.6; //scale based on 800x600
|
||||
iconWide = iconTall = (int)( scale * 16.0 );
|
||||
|
||||
int iconDefSize = (int)( scale * 32.0 );
|
||||
|
||||
int spacerX = XRES(5);
|
||||
|
||||
int x = xRight - len - spacerX - iconWide - XRES(10);
|
||||
|
||||
x -= iconDefSize;
|
||||
|
||||
surface()->DrawSetTextFont( m_hTextFont );
|
||||
int iFontTall = vgui::surface()->GetFontTall( m_hTextFont );
|
||||
int yText = y + ( iconDefSize - iFontTall ) / 2;
|
||||
|
||||
int boxWidth = len + iconWide + spacerX;
|
||||
|
||||
boxWidth += iconDefSize;
|
||||
|
||||
int boxHeight = m_flLineHeight;
|
||||
int boxBorder = XRES(2);
|
||||
|
||||
// Draw Defender's name
|
||||
int nameWidth = UTIL_ComputeStringWidth( m_hTextFont, killer ) + spacerX; // gap
|
||||
|
||||
x -= nameWidth;
|
||||
boxWidth += nameWidth;
|
||||
|
||||
DrawBackgroundBox( x-boxBorder, y-boxBorder, boxWidth+2*boxBorder, boxHeight+2*boxBorder, pItem->bLocalPlayerInvolved );
|
||||
|
||||
SetColorForNoticePlayer( iKillerTeam );
|
||||
|
||||
// Draw killer's name
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
surface()->DrawUnicodeString( killer );
|
||||
surface()->DrawGetTextPos( x, yText );
|
||||
|
||||
x += spacerX;
|
||||
|
||||
Color iconColor( 255, 80, 0, 255 );
|
||||
|
||||
// Draw shield + cap icon
|
||||
m_pIconDefended->DrawSelf( x, y, iconDefSize, iconDefSize, Color(255,255,255,255) );
|
||||
x += iconDefSize + spacerX;
|
||||
|
||||
const char *szMatName = GetMaterialNameFromIndex( pItem->iMaterial );
|
||||
|
||||
vgui::surface()->DrawSetColor( Color(255,255,255,255) );
|
||||
vgui::surface()->DrawSetTextureFile( m_iMaterialTexture, szMatName, true, false);
|
||||
|
||||
int iconY = y + iconDefSize / 2 - iconTall / 2;
|
||||
vgui::surface()->DrawTexturedRect( x, iconY, x + iconWide, iconY + iconTall );
|
||||
x += iconWide;
|
||||
|
||||
SetColorForNoticePlayer( iVictimTeam );
|
||||
|
||||
// Draw location name
|
||||
surface()->DrawSetTextFont( m_hTextFont ); //reset the font, draw icon can change it
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
|
||||
surface()->DrawUnicodeString( victim );
|
||||
|
||||
// return height of this item
|
||||
// base spacing on the height of the background box
|
||||
return boxHeight + boxBorder*2 + YRES(4);
|
||||
}
|
||||
|
||||
// X is right side, do a right align!
|
||||
int CHudDeathNotice::DrawDeathNoticeItem( DeathNoticeItem *pItem, int xRight, int y )
|
||||
{
|
||||
if ( pItem->bDominating )
|
||||
{
|
||||
return DrawDominationNoticeItem( pItem, xRight, y );
|
||||
}
|
||||
|
||||
bool bCapMsg = pItem->bCapMsg;
|
||||
|
||||
// Get the team numbers for the players involved
|
||||
int iKillerTeam = TEAM_UNASSIGNED;
|
||||
int iVictimTeam = TEAM_UNASSIGNED;
|
||||
|
||||
if ( bCapMsg )
|
||||
{
|
||||
iKillerTeam = pItem->Killer.iEntIndex;
|
||||
iVictimTeam = TEAM_UNASSIGNED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( g_PR )
|
||||
{
|
||||
iKillerTeam = g_PR->GetTeam( pItem->Killer.iEntIndex );
|
||||
iVictimTeam = g_PR->GetTeam( pItem->Victim.iEntIndex );
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t victim[ 256 ];
|
||||
wchar_t killer[ 256 ];
|
||||
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->Victim.szName, victim, sizeof( victim ) );
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->Killer.szName, killer, sizeof( killer ) );
|
||||
|
||||
// Get the local position for this notice
|
||||
int len = UTIL_ComputeStringWidth( m_hTextFont, victim );
|
||||
|
||||
int iconWide;
|
||||
int iconTall;
|
||||
|
||||
CHudTexture *icon = pItem->iconDeath;
|
||||
|
||||
Assert( icon );
|
||||
|
||||
if ( bCapMsg )
|
||||
{
|
||||
float scale = ( (float)ScreenHeight() / 480.0f ) * 0.6; //scale based on 800x600
|
||||
iconWide = iconTall = (int)( scale * 32.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !icon )
|
||||
return 0;
|
||||
|
||||
if( icon->bRenderUsingFont )
|
||||
{
|
||||
iconWide = surface()->GetCharacterWidth( icon->hFont, icon->cCharacterInFont );
|
||||
iconTall = surface()->GetFontTall( icon->hFont );
|
||||
}
|
||||
else
|
||||
{
|
||||
float scale = GetScale( icon->Width(), icon->Height(), XRES(cl_deathicon_width.GetInt()), YRES(cl_deathicon_height.GetInt()) );
|
||||
iconWide = (int)( scale * (float)icon->Width() );
|
||||
iconTall = (int)( scale * (float)icon->Height() );
|
||||
}
|
||||
}
|
||||
|
||||
int spacerX = XRES(5);
|
||||
|
||||
int x = xRight - len - spacerX - iconWide - XRES(10);
|
||||
|
||||
if ( pItem->bDefense )
|
||||
{
|
||||
x -= iconWide; //m_iDefendedIconSize;
|
||||
}
|
||||
|
||||
surface()->DrawSetTextFont( m_hTextFont );
|
||||
int iFontTall = vgui::surface()->GetFontTall( m_hTextFont );
|
||||
int boxWidth = len + iconWide + spacerX;
|
||||
|
||||
if ( pItem->bDefense )
|
||||
{
|
||||
boxWidth += iconWide; //m_iDefendedIconSize;
|
||||
}
|
||||
|
||||
int boxHeight = m_flLineHeight; //MIN( iconTall, m_flLineHeight );
|
||||
int boxBorder = XRES(2);
|
||||
|
||||
int yText = y + ( m_flLineHeight - iFontTall ) / 2;
|
||||
int yIcon = y + ( m_flLineHeight - iconTall ) / 2;
|
||||
|
||||
// Only draw killers name if it wasn't a suicide
|
||||
if ( !pItem->bSuicide )
|
||||
{
|
||||
int nameWidth = UTIL_ComputeStringWidth( m_hTextFont, killer ) + spacerX; // gap
|
||||
|
||||
x -= nameWidth;
|
||||
boxWidth += nameWidth;
|
||||
|
||||
DrawBackgroundBox( x-boxBorder, y-boxBorder, boxWidth+2*boxBorder, boxHeight+2*boxBorder, pItem->bLocalPlayerInvolved );
|
||||
|
||||
SetColorForNoticePlayer( iKillerTeam );
|
||||
|
||||
// Draw killer's name
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
const wchar_t *p = killer;
|
||||
while ( *p )
|
||||
{
|
||||
surface()->DrawUnicodeChar( *p++ );
|
||||
}
|
||||
surface()->DrawGetTextPos( x, yText );
|
||||
|
||||
x += spacerX;
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawBackgroundBox( x-boxBorder, y-boxBorder, boxWidth+2*boxBorder, boxHeight+2*boxBorder, pItem->bLocalPlayerInvolved );
|
||||
}
|
||||
|
||||
Color iconColor( 255, 80, 0, 255 );
|
||||
|
||||
// Draw death weapon or cap icon
|
||||
if ( bCapMsg )
|
||||
{
|
||||
const char *szMatName = GetMaterialNameFromIndex( pItem->iMaterial );
|
||||
|
||||
vgui::surface()->DrawSetColor( Color(255,255,255,255) );
|
||||
vgui::surface()->DrawSetTextureFile( m_iMaterialTexture, szMatName, true, false);
|
||||
vgui::surface()->DrawTexturedRect( x, yIcon, x + iconWide, yIcon + iconTall );
|
||||
x += iconWide + spacerX;
|
||||
}
|
||||
else
|
||||
{
|
||||
//If we're using a font char, this will ignore iconTall and iconWide
|
||||
icon->DrawSelf( x, yIcon, iconWide, iconTall, iconColor );
|
||||
x += iconWide + spacerX;
|
||||
}
|
||||
|
||||
SetColorForNoticePlayer( iVictimTeam );
|
||||
|
||||
// Draw victims name
|
||||
surface()->DrawSetTextFont( m_hTextFont ); //reset the font, draw icon can change it
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
const wchar_t *p = victim;
|
||||
while ( *p )
|
||||
{
|
||||
surface()->DrawUnicodeChar( *p++ );
|
||||
}
|
||||
|
||||
// return height of this item
|
||||
// base spacing on the height of the background box
|
||||
return boxHeight + boxBorder*2 + YRES(4);
|
||||
}
|
||||
|
||||
int CHudDeathNotice::DrawDominationNoticeItem( DeathNoticeItem *pItem, int xRight, int y )
|
||||
{
|
||||
// Get the team numbers for the players involved
|
||||
int iKillerTeam = TEAM_UNASSIGNED;
|
||||
int iVictimTeam = TEAM_UNASSIGNED;
|
||||
|
||||
if( g_PR )
|
||||
{
|
||||
iKillerTeam = g_PR->GetTeam( pItem->Killer.iEntIndex );
|
||||
iVictimTeam = g_PR->GetTeam( pItem->Victim.iEntIndex );
|
||||
}
|
||||
|
||||
wchar_t victim[ 256 ];
|
||||
wchar_t killer[ 256 ];
|
||||
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->Victim.szName, victim, sizeof( victim ) );
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pItem->Killer.szName, killer, sizeof( killer ) );
|
||||
|
||||
// Get the local position for this notice
|
||||
int len = UTIL_ComputeStringWidth( m_hTextFont, victim );
|
||||
|
||||
int iconWide;
|
||||
int iconTall;
|
||||
|
||||
Assert( pItem->iconDeath );
|
||||
|
||||
CHudTexture *icon = pItem->iconDeath;
|
||||
|
||||
if ( !icon )
|
||||
return 0;
|
||||
|
||||
if( icon->bRenderUsingFont )
|
||||
{
|
||||
iconWide = surface()->GetCharacterWidth( icon->hFont, icon->cCharacterInFont );
|
||||
iconTall = surface()->GetFontTall( icon->hFont );
|
||||
}
|
||||
else
|
||||
{
|
||||
float scale = GetScale( icon->Width(), icon->Height(), XRES(cl_deathicon_width.GetInt()), YRES(cl_deathicon_height.GetInt()) );
|
||||
iconWide = (int)( scale * (float)icon->Width() );
|
||||
iconTall = (int)( scale * (float)icon->Height() );
|
||||
}
|
||||
|
||||
int spacerX = XRES(5);
|
||||
|
||||
int x = xRight - len - spacerX - iconWide - XRES(10);
|
||||
|
||||
surface()->DrawSetTextFont( m_hTextFont );
|
||||
int iFontTall = vgui::surface()->GetFontTall( m_hTextFont );
|
||||
int boxWidth = len + iconWide + spacerX;
|
||||
|
||||
int iDominatingLen = UTIL_ComputeStringWidth( m_hTextFont, pItem->wzInfoText ) + XRES(2);
|
||||
x -= iDominatingLen;
|
||||
boxWidth += iDominatingLen;
|
||||
|
||||
int boxHeight = m_flLineHeight; //MIN( iconTall, m_flLineHeight );
|
||||
int boxBorder = XRES(2);
|
||||
|
||||
int yText = y + ( m_flLineHeight - iFontTall ) / 2;
|
||||
int yIcon = y + ( m_flLineHeight - iconTall ) / 2;
|
||||
|
||||
int nameWidth = UTIL_ComputeStringWidth( m_hTextFont, killer ) + spacerX; // gap
|
||||
|
||||
x -= nameWidth;
|
||||
boxWidth += nameWidth;
|
||||
|
||||
DrawBackgroundBox( x-boxBorder, y-boxBorder, boxWidth+2*boxBorder, boxHeight+2*boxBorder, pItem->bLocalPlayerInvolved );
|
||||
|
||||
SetColorForNoticePlayer( iKillerTeam );
|
||||
|
||||
// Draw killer's name
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
const wchar_t *p = killer;
|
||||
while ( *p )
|
||||
{
|
||||
surface()->DrawUnicodeChar( *p++ );
|
||||
}
|
||||
surface()->DrawGetTextPos( x, yText );
|
||||
|
||||
x += spacerX;
|
||||
|
||||
Color iconColor( 255, 80, 0, 255 );
|
||||
|
||||
//If we're using a font char, this will ignore iconTall and iconWide
|
||||
icon->DrawSelf( x, yIcon, iconWide, iconTall, iconColor );
|
||||
x += iconWide + spacerX;
|
||||
|
||||
surface()->DrawSetTextColor( Color(255,255,255,255) );
|
||||
|
||||
// Draw dominating string
|
||||
surface()->DrawSetTextFont( m_hTextFont ); //reset the font, draw icon can change it
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
p = pItem->wzInfoText;
|
||||
while ( *p )
|
||||
{
|
||||
surface()->DrawUnicodeChar( *p++ );
|
||||
}
|
||||
x += iDominatingLen;
|
||||
|
||||
SetColorForNoticePlayer( iVictimTeam );
|
||||
|
||||
// Draw victims name
|
||||
//surface()->DrawSetTextFont( m_hTextFont ); //reset the font, draw icon can change it
|
||||
surface()->DrawSetTextPos( x, yText );
|
||||
p = victim;
|
||||
while ( *p )
|
||||
{
|
||||
surface()->DrawUnicodeChar( *p++ );
|
||||
}
|
||||
|
||||
// return height of this item
|
||||
// base spacing on the height of the background box
|
||||
return boxHeight + boxBorder*2 + YRES(4);
|
||||
}
|
||||
|
||||
ConVar cl_deathicon_bg_alpha( "cl_deathicon_bg_alpha", "1.0" );
|
||||
|
||||
void CHudDeathNotice::DrawBackgroundBox( int x, int y, int w, int h, bool bLocalPlayerInvolved )
|
||||
{
|
||||
Panel::DrawBox( x, y, w, h,
|
||||
bLocalPlayerInvolved ? m_ActiveBackgroundColor : m_BackgroundColor,
|
||||
cl_deathicon_bg_alpha.GetFloat() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This message handler may be better off elsewhere
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::RetireExpiredDeathNotices( void )
|
||||
{
|
||||
// Loop backwards because we might remove one
|
||||
int iSize = m_DeathNotices.Size();
|
||||
for ( int i = iSize-1; i >= 0; i-- )
|
||||
{
|
||||
if ( m_DeathNotices[i].flDisplayTime < gpGlobals->curtime )
|
||||
{
|
||||
m_DeathNotices.Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Server's told us that someone's died
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::FireGameEvent( IGameEvent * event)
|
||||
{
|
||||
if (!g_PR)
|
||||
return;
|
||||
|
||||
if ( hud_deathnotice_time.GetFloat() == 0 )
|
||||
return;
|
||||
|
||||
C_DODPlayer *pLocal = C_DODPlayer::GetLocalDODPlayer();
|
||||
|
||||
Assert( pLocal );
|
||||
|
||||
if ( !pLocal )
|
||||
return;
|
||||
|
||||
int iLocalPlayerIndex = pLocal->entindex();
|
||||
|
||||
const char *pEventName = event->GetName();
|
||||
|
||||
if ( Q_strcmp( "dod_point_captured", pEventName ) == 0 )
|
||||
{
|
||||
// Cap point index
|
||||
int cp = event->GetInt( "cp", -1 );
|
||||
Assert( cp >= 0 );
|
||||
|
||||
// Cap point name ( MATTTODO: can't we find this from the point index ? )
|
||||
const char *pName = event->GetString( "cpname", "Unnamed Control Point" );
|
||||
const wchar_t *pBuf = g_pVGuiLocalize->Find( pName );
|
||||
|
||||
// Array of capper indeces
|
||||
const char *cappers = event->GetString("cappers");
|
||||
|
||||
DeathNoticeItem capMsg;
|
||||
capMsg.bCapMsg = true;
|
||||
capMsg.bSuicide = false;
|
||||
capMsg.bDefense = false;
|
||||
capMsg.flDisplayTime = gpGlobals->curtime + hud_deathnotice_time.GetFloat();
|
||||
capMsg.bLocalPlayerInvolved = false;
|
||||
|
||||
char szCappers[256];
|
||||
szCappers[0] = '\0';
|
||||
|
||||
int len = Q_strlen(cappers);
|
||||
for( int i=0;i<len;i++ )
|
||||
{
|
||||
int iPlayerIndex = (int)cappers[i];
|
||||
|
||||
if ( iPlayerIndex == iLocalPlayerIndex )
|
||||
capMsg.bLocalPlayerInvolved = true;
|
||||
|
||||
Assert( iPlayerIndex > 0 && iPlayerIndex <= gpGlobals->maxClients );
|
||||
|
||||
const char *pPlayerName = g_PR->GetPlayerName( iPlayerIndex );
|
||||
|
||||
if ( i == 0 )
|
||||
{
|
||||
// use first player as the team
|
||||
capMsg.Killer.iEntIndex = g_PR->GetTeam( iPlayerIndex );
|
||||
capMsg.iMaterial = g_pObjectiveResource->GetIconForTeam( cp, capMsg.Killer.iEntIndex );
|
||||
|
||||
if ( g_pObjectiveResource->GetBombsRequired( cp ) > 0 )
|
||||
{
|
||||
capMsg.iMaterial = g_pObjectiveResource->GetCPBombedIcon( cp );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncat( szCappers, ", ", sizeof(szCappers), 2 );
|
||||
}
|
||||
|
||||
Q_strncat( szCappers, pPlayerName, sizeof(szCappers), COPY_ALL_CHARACTERS );
|
||||
}
|
||||
|
||||
Q_strncpy( capMsg.Killer.szName, szCappers, sizeof(capMsg.Killer.szName) );
|
||||
|
||||
if ( pBuf )
|
||||
{
|
||||
g_pVGuiLocalize->ConvertUnicodeToANSI( pBuf, capMsg.Victim.szName, sizeof(capMsg.Victim.szName) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncpy( capMsg.Victim.szName, pName, sizeof(capMsg.Victim.szName) );
|
||||
}
|
||||
|
||||
// Do we have too many death messages in the queue?
|
||||
if ( m_DeathNotices.Count() > 0 &&
|
||||
m_DeathNotices.Count() >= (int)m_flMaxDeathNotices )
|
||||
{
|
||||
// Remove the oldest one in the queue, which will always be the first
|
||||
m_DeathNotices.Remove(0);
|
||||
}
|
||||
|
||||
m_DeathNotices.AddToTail( capMsg );
|
||||
|
||||
// print a log message
|
||||
|
||||
char szLogMsg[512];
|
||||
|
||||
Q_snprintf( szLogMsg, sizeof( szLogMsg ), "%s captured %s for the %s\n",
|
||||
capMsg.Killer.szName,
|
||||
capMsg.Victim.szName,
|
||||
capMsg.Killer.iEntIndex == TEAM_ALLIES ? "U.S. Army" : "Wermacht" );
|
||||
|
||||
Msg( "%s",szLogMsg );
|
||||
}
|
||||
else if ( Q_strcmp( "dod_capture_blocked", pEventName ) == 0 )
|
||||
{
|
||||
// Cap point index
|
||||
int cp = event->GetInt( "cp", -1 );
|
||||
Assert( cp >= 0 );
|
||||
|
||||
// Cap point name
|
||||
const char *pName = event->GetString( "cpname", "Unnamed Control Point" );
|
||||
const wchar_t *pBuf = g_pVGuiLocalize->Find( pName );
|
||||
|
||||
// A single blocker entindex
|
||||
int iBlocker = event->GetInt("blocker");
|
||||
|
||||
DeathNoticeItem capMsg;
|
||||
capMsg.bCapMsg = true;
|
||||
capMsg.bSuicide = false;
|
||||
capMsg.bDefense = true;
|
||||
capMsg.flDisplayTime = gpGlobals->curtime + hud_deathnotice_time.GetFloat();
|
||||
capMsg.bLocalPlayerInvolved = false;
|
||||
|
||||
capMsg.Killer.iEntIndex = g_PR->GetTeam( iBlocker );
|
||||
capMsg.iMaterial = g_pObjectiveResource->GetIconForTeam( cp, capMsg.Killer.iEntIndex );
|
||||
|
||||
if ( iBlocker == iLocalPlayerIndex )
|
||||
capMsg.bLocalPlayerInvolved = true;
|
||||
|
||||
Q_strncpy( capMsg.Killer.szName, g_PR->GetPlayerName( iBlocker ), sizeof(capMsg.Killer.szName) );
|
||||
|
||||
char buf[128];
|
||||
|
||||
if ( pBuf )
|
||||
{
|
||||
g_pVGuiLocalize->ConvertUnicodeToANSI( pBuf, buf, sizeof(buf) );
|
||||
pName = buf;
|
||||
}
|
||||
|
||||
Q_snprintf( capMsg.Victim.szName, sizeof(capMsg.Victim.szName), " - %s", pName );
|
||||
|
||||
// Do we have too many death messages in the queue?
|
||||
if ( m_DeathNotices.Count() > 0 &&
|
||||
m_DeathNotices.Count() >= (int)m_flMaxDeathNotices )
|
||||
{
|
||||
// Remove the oldest one in the queue, which will always be the first
|
||||
m_DeathNotices.Remove(0);
|
||||
}
|
||||
|
||||
m_DeathNotices.AddToTail( capMsg );
|
||||
}
|
||||
else if ( Q_strcmp( "player_death", pEventName ) == 0 )
|
||||
{
|
||||
int killer = engine->GetPlayerForUserID( event->GetInt("attacker") );
|
||||
int victim = engine->GetPlayerForUserID( event->GetInt("userid") );
|
||||
const char *killedwith = event->GetString( "weapon" );
|
||||
|
||||
char fullkilledwith[128];
|
||||
if ( killedwith && *killedwith )
|
||||
{
|
||||
Q_snprintf( fullkilledwith, sizeof(fullkilledwith), "d_%s", killedwith );
|
||||
}
|
||||
else
|
||||
{
|
||||
fullkilledwith[0] = 0;
|
||||
}
|
||||
|
||||
// Do we have too many death messages in the queue?
|
||||
if ( m_DeathNotices.Count() > 0 &&
|
||||
m_DeathNotices.Count() >= (int)m_flMaxDeathNotices )
|
||||
{
|
||||
// Remove the oldest one in the queue, which will always be the first
|
||||
m_DeathNotices.Remove(0);
|
||||
}
|
||||
|
||||
// Get the names of the players
|
||||
const char *killer_name = g_PR->GetPlayerName( killer );
|
||||
const char *victim_name = g_PR->GetPlayerName( victim );
|
||||
|
||||
if ( !killer_name )
|
||||
killer_name = "";
|
||||
if ( !victim_name )
|
||||
victim_name = "";
|
||||
|
||||
// Make a new death notice
|
||||
DeathNoticeItem deathMsg;
|
||||
deathMsg.Killer.iEntIndex = killer;
|
||||
deathMsg.Victim.iEntIndex = victim;
|
||||
Q_strncpy( deathMsg.Killer.szName, killer_name, MAX_PLAYER_NAME_LENGTH );
|
||||
Q_strncpy( deathMsg.Victim.szName, victim_name, MAX_PLAYER_NAME_LENGTH );
|
||||
deathMsg.flDisplayTime = gpGlobals->curtime + hud_deathnotice_time.GetFloat();
|
||||
deathMsg.bSuicide = ( !killer || killer == victim );
|
||||
deathMsg.bCapMsg = false;
|
||||
deathMsg.bDefense = false;
|
||||
deathMsg.iMaterial = -1;
|
||||
deathMsg.bLocalPlayerInvolved = ( killer == iLocalPlayerIndex || victim == iLocalPlayerIndex );
|
||||
|
||||
// Try and find the death identifier in the icon list
|
||||
deathMsg.iconDeath = gHUD.GetIcon( fullkilledwith );
|
||||
|
||||
if ( !deathMsg.iconDeath )
|
||||
{
|
||||
// Can't find it, so use the default skull & crossbones icon
|
||||
deathMsg.iconDeath = m_iconD_skull;
|
||||
}
|
||||
|
||||
// Add it to our list of death notices
|
||||
m_DeathNotices.AddToTail( deathMsg );
|
||||
|
||||
if ( event->GetInt( "dominated" ) > 0 )
|
||||
{
|
||||
AddAdditionalMsg( killer, victim, "#Msg_Dominating" );
|
||||
PlayRivalrySounds( killer, victim, DOD_DEATHFLAG_DOMINATION );
|
||||
}
|
||||
if ( event->GetInt( "revenge" ) > 0 )
|
||||
{
|
||||
AddAdditionalMsg( killer, victim, "#Msg_Revenge" );
|
||||
PlayRivalrySounds( killer, victim, DOD_DEATHFLAG_REVENGE );
|
||||
}
|
||||
|
||||
char sDeathMsg[512];
|
||||
|
||||
// Record the death notice in the console
|
||||
if ( deathMsg.bSuicide )
|
||||
{
|
||||
if ( !strcmp( fullkilledwith, "d_worldspawn" ) )
|
||||
{
|
||||
Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s died.\n", deathMsg.Victim.szName );
|
||||
}
|
||||
else //d_world
|
||||
{
|
||||
Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s suicided.\n", deathMsg.Victim.szName );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintf( sDeathMsg, sizeof( sDeathMsg ), "%s killed %s", deathMsg.Killer.szName, deathMsg.Victim.szName );
|
||||
|
||||
if ( fullkilledwith && *fullkilledwith && (*fullkilledwith > 13 ) )
|
||||
{
|
||||
Q_strncat( sDeathMsg, VarArgs( " with %s.\n", fullkilledwith+2 ), sizeof( sDeathMsg ), COPY_ALL_CHARACTERS );
|
||||
}
|
||||
}
|
||||
|
||||
Msg( "%s",sDeathMsg );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Adds an additional death message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDeathNotice::AddAdditionalMsg( int iKillerID, int iVictimID, const char *pMsgKey )
|
||||
{
|
||||
int iMsg = m_DeathNotices.AddToTail();
|
||||
DeathNoticeItem &msg = m_DeathNotices[iMsg];
|
||||
|
||||
msg.Killer.iEntIndex = iKillerID;
|
||||
msg.Victim.iEntIndex = iVictimID;
|
||||
Q_strncpy( msg.Killer.szName, g_PR->GetPlayerName( iKillerID ), ARRAYSIZE( msg.Killer.szName ) );
|
||||
Q_strncpy( msg.Victim.szName, g_PR->GetPlayerName( iVictimID ), ARRAYSIZE( msg.Victim.szName ) );
|
||||
msg.flDisplayTime = gpGlobals->curtime + hud_deathnotice_time.GetFloat();
|
||||
msg.bSuicide = false;
|
||||
msg.bCapMsg = false;
|
||||
msg.bDefense = false;
|
||||
msg.iMaterial = -1;
|
||||
|
||||
msg.bDominating = true;
|
||||
const wchar_t *wzMsg = g_pVGuiLocalize->Find( pMsgKey );
|
||||
if ( wzMsg )
|
||||
{
|
||||
V_wcsncpy( msg.wzInfoText, wzMsg, sizeof( msg.wzInfoText ) );
|
||||
}
|
||||
msg.iconDeath = m_iconDomination;
|
||||
|
||||
int iLocalPlayerIndex = GetLocalPlayerIndex();
|
||||
if ( iLocalPlayerIndex == iVictimID || iLocalPlayerIndex == iKillerID )
|
||||
{
|
||||
msg.bLocalPlayerInvolved = true;
|
||||
}
|
||||
}
|
||||
|
||||
ConVar dod_playrivalrysounds( "dod_playrivalrysounds", "1", FCVAR_ARCHIVE );
|
||||
|
||||
void CHudDeathNotice::PlayRivalrySounds( int iKillerIndex, int iVictimIndex, int iType )
|
||||
{
|
||||
if ( dod_playrivalrysounds.GetBool() == false )
|
||||
return;
|
||||
|
||||
int iLocalPlayerIndex = GetLocalPlayerIndex();
|
||||
|
||||
//We're not involved in this kill
|
||||
if ( iKillerIndex != iLocalPlayerIndex && iVictimIndex != iLocalPlayerIndex )
|
||||
return;
|
||||
|
||||
const char *pszSoundName = NULL;
|
||||
|
||||
if ( iType == DOD_DEATHFLAG_DOMINATION )
|
||||
{
|
||||
if ( iKillerIndex == iLocalPlayerIndex )
|
||||
{
|
||||
pszSoundName = "Game.Domination";
|
||||
}
|
||||
else if ( iVictimIndex == iLocalPlayerIndex )
|
||||
{
|
||||
pszSoundName = "Game.Nemesis";
|
||||
}
|
||||
}
|
||||
else if ( iType == DOD_DEATHFLAG_REVENGE )
|
||||
{
|
||||
pszSoundName = "Game.Revenge";
|
||||
}
|
||||
|
||||
CLocalPlayerFilter filter;
|
||||
C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, pszSoundName );
|
||||
}
|
||||
Reference in New Issue
Block a user