diff options
Diffstat (limited to 'game/client/history_resource.cpp')
| -rw-r--r-- | game/client/history_resource.cpp | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/game/client/history_resource.cpp b/game/client/history_resource.cpp new file mode 100644 index 0000000..c0743b4 --- /dev/null +++ b/game/client/history_resource.cpp @@ -0,0 +1,465 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Item pickup history displayed onscreen when items are picked up. +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "history_resource.h" +#include "hud_macros.h" +#include <vgui_controls/Controls.h> +#include <vgui/ILocalize.h> +#include <vgui/ISurface.h> +#include "iclientmode.h" +#include "vgui_controls/AnimationController.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; + +extern ConVar hud_drawhistory_time; + +DECLARE_HUDELEMENT( CHudHistoryResource ); +DECLARE_HUD_MESSAGE( CHudHistoryResource, ItemPickup ); +DECLARE_HUD_MESSAGE( CHudHistoryResource, AmmoDenied ); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CHudHistoryResource::CHudHistoryResource( const char *pElementName ) : + CHudElement( pElementName ), BaseClass( NULL, "HudHistoryResource" ) +{ + vgui::Panel *pParent = g_pClientMode->GetViewport(); + SetParent( pParent ); + m_bDoNotDraw = true; + m_wcsAmmoFullMsg[0] = 0; + m_bNeedsDraw = false; + SetHiddenBits( HIDEHUD_MISCSTATUS ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudHistoryResource::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + SetPaintBackgroundEnabled( false ); + + // lookup text to display for ammo full message + wchar_t *wcs = g_pVGuiLocalize->Find("#hl2_AmmoFull"); + if (wcs) + { + wcsncpy(m_wcsAmmoFullMsg, wcs, sizeof(m_wcsAmmoFullMsg) / sizeof(wchar_t)); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudHistoryResource::Init( void ) +{ + HOOK_HUD_MESSAGE( CHudHistoryResource, ItemPickup ); + HOOK_HUD_MESSAGE( CHudHistoryResource, AmmoDenied ); + + Reset(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudHistoryResource::Reset( void ) +{ + m_PickupHistory.RemoveAll(); + m_iCurrentHistorySlot = 0; + m_bDoNotDraw = true; +} + +//----------------------------------------------------------------------------- +// Purpose: these kept only for hl1-port compatibility +//----------------------------------------------------------------------------- +void CHudHistoryResource::SetHistoryGap( int iNewHistoryGap ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: adds an element to the history +//----------------------------------------------------------------------------- +void CHudHistoryResource::AddToHistory( C_BaseCombatWeapon *weapon ) +{ + // don't draw exhaustable weapons (grenades) since they'll have an ammo pickup icon as well + if ( weapon->GetWpnData().iFlags & ITEM_FLAG_EXHAUSTIBLE ) + return; + + int iId = weapon->entindex(); + + // don't show the same weapon twice + for ( int i = 0; i < m_PickupHistory.Count(); i++ ) + { + if ( m_PickupHistory[i].iId == iId ) + { + // it's already in list + return; + } + } + + AddIconToHistory( HISTSLOT_WEAP, iId, weapon, 0, NULL ); +} + +//----------------------------------------------------------------------------- +// Purpose: Add a new entry to the pickup history +//----------------------------------------------------------------------------- +void CHudHistoryResource::AddToHistory( int iType, int iId, int iCount ) +{ + // Ignore adds with no count + if ( iType == HISTSLOT_AMMO ) + { + if ( !iCount ) + return; + +#if defined( CSTRIKE_DLL ) + // don't leave blank gaps for ammo we're not going to display + const FileWeaponInfo_t *pWpnInfo = gWR.GetWeaponFromAmmo( iId ); + if ( pWpnInfo && ( pWpnInfo->iMaxClip1 >= 0 || pWpnInfo->iMaxClip2 >= 0 ) ) + { + if ( !pWpnInfo->iconSmall ) + return; + } +#endif + + // clear out any ammo pickup denied icons, since we can obviously pickup again + for ( int i = 0; i < m_PickupHistory.Count(); i++ ) + { + if ( m_PickupHistory[i].type == HISTSLOT_AMMODENIED && m_PickupHistory[i].iId == iId ) + { + // kill the old entry + m_PickupHistory[i].DisplayTime = 0.0f; + // change the pickup to be in this entry + m_iCurrentHistorySlot = i; + break; + } + } + } + + AddIconToHistory( iType, iId, NULL, iCount, NULL ); +} + +//----------------------------------------------------------------------------- +// Purpose: Add a new entry to the pickup history +//----------------------------------------------------------------------------- +void CHudHistoryResource::AddToHistory( int iType, const char *szName, int iCount ) +{ + if ( iType != HISTSLOT_ITEM ) + return; + + // Get the item's icon + CHudTexture *i = gHUD.GetIcon( szName ); + if ( i == NULL ) + return; + + AddIconToHistory( iType, 1, NULL, iCount, i ); +} + +//----------------------------------------------------------------------------- +// Purpose: adds a history icon +//----------------------------------------------------------------------------- +void CHudHistoryResource::AddIconToHistory( int iType, int iId, C_BaseCombatWeapon *weapon, int iCount, CHudTexture *icon ) +{ + m_bNeedsDraw = true; + + // Check to see if the pic would have to be drawn too high. If so, start again from the bottom + if ( (m_flHistoryGap * (m_iCurrentHistorySlot+1)) > GetTall() ) + { + m_iCurrentHistorySlot = 0; + } + + // If the history resource is appearing, slide the hint message element down + if ( m_iCurrentHistorySlot == 0 ) + { + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HintMessageLower" ); + } + + // ensure the size + m_PickupHistory.EnsureCount(m_iCurrentHistorySlot + 1); + + // default to just writing to the first slot + HIST_ITEM *freeslot = &m_PickupHistory[m_iCurrentHistorySlot]; + + if ( iType == HISTSLOT_AMMODENIED && freeslot->DisplayTime ) + { + // don't override existing pickup icons with denied icons + return; + } + + freeslot->iId = iId; + freeslot->icon = icon; + freeslot->type = iType; + freeslot->m_hWeapon = weapon; + freeslot->iCount = iCount; + + if (iType == HISTSLOT_AMMODENIED) + { + freeslot->DisplayTime = gpGlobals->curtime + (hud_drawhistory_time.GetFloat() / 2.0f); + } + else + { + freeslot->DisplayTime = gpGlobals->curtime + hud_drawhistory_time.GetFloat(); + } + + ++m_iCurrentHistorySlot; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handle an item pickup event from the server +//----------------------------------------------------------------------------- +void CHudHistoryResource::MsgFunc_ItemPickup( bf_read &msg ) +{ + char szName[1024]; + + msg.ReadString( szName, sizeof(szName) ); + + // Add the item to the history + AddToHistory( HISTSLOT_ITEM, szName ); +} + +//----------------------------------------------------------------------------- +// Purpose: ammo denied message +//----------------------------------------------------------------------------- +void CHudHistoryResource::MsgFunc_AmmoDenied( bf_read &msg ) +{ + int iAmmo = msg.ReadShort(); + + // see if there are any existing ammo items of that type + for ( int i = 0; i < m_PickupHistory.Count(); i++ ) + { + if ( m_PickupHistory[i].type == HISTSLOT_AMMO && m_PickupHistory[i].iId == iAmmo ) + { + // it's already in the list as a pickup, ignore + return; + } + } + + // see if there are any denied ammo icons, if so refresh their timer + for ( int i = 0; i < m_PickupHistory.Count(); i++ ) + { + if ( m_PickupHistory[i].type == HISTSLOT_AMMODENIED && m_PickupHistory[i].iId == iAmmo ) + { + // it's already in the list, refresh + m_PickupHistory[i].DisplayTime = gpGlobals->curtime + (hud_drawhistory_time.GetFloat() / 2.0f); + m_bNeedsDraw = true; + return; + } + } + + // add into the list + AddToHistory( HISTSLOT_AMMODENIED, iAmmo, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: If there aren't any items in the history, clear it out. +//----------------------------------------------------------------------------- +void CHudHistoryResource::CheckClearHistory( void ) +{ + for ( int i = 0; i < m_PickupHistory.Count(); i++ ) + { + if ( m_PickupHistory[i].type ) + return; + } + + m_iCurrentHistorySlot = 0; + + // Slide the hint message element back up + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HintMessageRaise" ); +} + +//----------------------------------------------------------------------------- +// Purpose: Save CPU cycles by letting the HUD system early cull +// costly traversal. Called per frame, return true if thinking and +// painting need to occur. +//----------------------------------------------------------------------------- +bool CHudHistoryResource::ShouldDraw( void ) +{ +#ifdef TF_CLIENT_DLL + return false; +#else + return ( ( m_iCurrentHistorySlot > 0 || m_bNeedsDraw ) && CHudElement::ShouldDraw() ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Draw the pickup history +//----------------------------------------------------------------------------- +void CHudHistoryResource::Paint( void ) +{ + if ( m_bDoNotDraw ) + { + // this is to not draw things until the first rendered + m_bDoNotDraw = false; + return; + } + + // set when drawing should occur + // will be set if valid drawing does occur + m_bNeedsDraw = false; + + int wide, tall; + GetSize( wide, tall ); + + for ( int i = 0; i < m_PickupHistory.Count(); i++ ) + { + if ( m_PickupHistory[i].type ) + { + m_PickupHistory[i].DisplayTime = MIN( m_PickupHistory[i].DisplayTime, gpGlobals->curtime + hud_drawhistory_time.GetFloat() ); + if ( m_PickupHistory[i].DisplayTime <= gpGlobals->curtime ) + { + // pic drawing time has expired + memset( &m_PickupHistory[i], 0, sizeof(HIST_ITEM) ); + CheckClearHistory(); + continue; + } + + float elapsed = m_PickupHistory[i].DisplayTime - gpGlobals->curtime; + float scale = elapsed * 80; + Color clr = gHUD.m_clrNormal; + clr[3] = MIN( scale, 255 ); + + bool bUseAmmoFullMsg = false; + + // get the icon and number to draw + const CHudTexture *itemIcon = NULL; + const CHudTexture *itemAmmoIcon = NULL; + int iAmount = 0; + bool bHalfHeight = true; + + switch ( m_PickupHistory[i].type ) + { + case HISTSLOT_AMMO: + { + // Get the weapon we belong to +#ifndef HL2MP + const FileWeaponInfo_t *pWpnInfo = gWR.GetWeaponFromAmmo( m_PickupHistory[i].iId ); + if ( pWpnInfo && ( pWpnInfo->iMaxClip1 >= 0 || pWpnInfo->iMaxClip2 >= 0 ) ) + { + // The weapon will be the main icon, and the ammo the smaller + itemIcon = pWpnInfo->iconSmall; + itemAmmoIcon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId ); + } + else +#endif // HL2MP + { + itemIcon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId ); + itemAmmoIcon = NULL; + } + +#ifdef CSTRIKE_DLL + // show grenades as the weapon icon + if ( pWpnInfo && pWpnInfo->iFlags & ITEM_FLAG_EXHAUSTIBLE ) + { + itemIcon = pWpnInfo->iconActive; + itemAmmoIcon = NULL; + bHalfHeight = false; + } +#endif + + iAmount = m_PickupHistory[i].iCount; + } + break; + case HISTSLOT_AMMODENIED: + { + itemIcon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId ); + iAmount = 0; + bUseAmmoFullMsg = true; + // display as red + clr = gHUD.m_clrCaution; + clr[3] = MIN( scale, 255 ); + } + break; + + case HISTSLOT_WEAP: + { + C_BaseCombatWeapon *pWeapon = m_PickupHistory[i].m_hWeapon; + if ( !pWeapon ) + return; + + if ( !pWeapon->HasAmmo() ) + { + // if the weapon doesn't have ammo, display it as red + clr = gHUD.m_clrCaution; + clr[3] = MIN( scale, 255 ); + } + + itemIcon = pWeapon->GetSpriteInactive(); + bHalfHeight = false; + } + break; + case HISTSLOT_ITEM: + { + if ( !m_PickupHistory[i].iId ) + continue; + + itemIcon = m_PickupHistory[i].icon; + bHalfHeight = false; + } + break; + default: + // unknown history type + Assert( 0 ); + break; + } + + if ( !itemIcon ) + continue; + + if ( clr[3] ) + { + // valid drawing will occur + m_bNeedsDraw = true; + } + + int ypos = tall - (m_flHistoryGap * (i + 1)); + int xpos = wide - itemIcon->Width() - m_flIconInset; + +#ifndef HL2MP + // Adjust for a half-height icon + if ( bHalfHeight ) + { + ypos += itemIcon->Height() / 2; + } +#endif // HL2MP + + itemIcon->DrawSelf( xpos, ypos, clr ); + + if ( itemAmmoIcon ) + { + itemAmmoIcon->DrawSelf( xpos - ( itemAmmoIcon->Width() * 1.25f ), ypos, clr ); + } + + if ( iAmount ) + { + wchar_t text[16]; + _snwprintf( text, sizeof( text ) / sizeof(wchar_t), L"%i", m_PickupHistory[i].iCount ); + + // offset the number to sit properly next to the icon + ypos -= ( surface()->GetFontTall( m_hNumberFont ) - itemIcon->Height() ) / 2; + + vgui::surface()->DrawSetTextFont( m_hNumberFont ); + vgui::surface()->DrawSetTextColor( clr ); + vgui::surface()->DrawSetTextPos( wide - m_flTextInset, ypos ); + vgui::surface()->DrawUnicodeString( text ); + } + else if ( bUseAmmoFullMsg ) + { + // offset the number to sit properly next to the icon + ypos -= ( surface()->GetFontTall( m_hTextFont ) - itemIcon->Height() ) / 2; + + vgui::surface()->DrawSetTextFont( m_hTextFont ); + vgui::surface()->DrawSetTextColor( clr ); + vgui::surface()->DrawSetTextPos( wide - m_flTextInset, ypos ); + vgui::surface()->DrawUnicodeString( m_wcsAmmoFullMsg ); + } + } + } +} + + |