summaryrefslogtreecommitdiff
path: root/game/client/dod/dod_hud_deathnotice.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/dod/dod_hud_deathnotice.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/client/dod/dod_hud_deathnotice.cpp')
-rw-r--r--game/client/dod/dod_hud_deathnotice.cpp942
1 files changed, 942 insertions, 0 deletions
diff --git a/game/client/dod/dod_hud_deathnotice.cpp b/game/client/dod/dod_hud_deathnotice.cpp
new file mode 100644
index 0000000..c00be07
--- /dev/null
+++ b/game/client/dod/dod_hud_deathnotice.cpp
@@ -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 );
+} \ No newline at end of file