#include "cbase.h" #include "asw_hud_master.h" #include "clientmode_asw.h" #include "vgui/ISurface.h" #include "bitmap/psheet.h" #include "vgui/ILocalize.h" #include "cdll_bounded_cvars.h" #include "VGUIMatSurface/IMatSystemSurface.h" #include "hud_macros.h" #include "ammodef.h" #include "asw_input.h" #include "c_asw_marine.h" #include "c_asw_marine_resource.h" #include "c_asw_game_resource.h" #include "asw_marine_profile.h" #include "c_asw_weapon.h" #include "asw_weapon_parse.h" #include "asw_equipment_list.h" #include "asw_circularprogressbar.h" #include // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" extern ConVar asw_draw_hud; extern ConVar asw_hud_alpha; using namespace vgui; DECLARE_HUDELEMENT( CASW_Hud_Master ); DECLARE_HUD_MESSAGE( CASW_Hud_Master, ASWOrderUseItemFX ); DECLARE_HUD_MESSAGE( CASW_Hud_Master, ASWOrderStopItemFX ); DECLARE_HUD_MESSAGE( CASW_Hud_Master, ASWInvalidDesination ); ///////////////////////////////////////////// // DO NOT CHANGE THE ORDER OF THESE UNLESS YOU // CHANGE THE ORDER IN THE PARTICLE SHEET AS WELL // "materialsrc\vgui\swarm\EquipIcons\particles\EquipUseIcons_particle.mks" // They need to match exactly! ///////////////////////////////////////////// #define NUM_USE_ITEM_ORDER_CLASSES 19 const char *pszUseItemOrderClasses[NUM_USE_ITEM_ORDER_CLASSES] = { "cancel", "asw_weapon_buff_grenade", "asw_weapon_freeze_grenades", "asw_weapon_grenades", "asw_weapon_laser_mines", "asw_weapon_mines", "asw_weapon_tesla_trap", "asw_weapon_heal_grenade", "asw_weapon_sentry", "asw_weapon_sentry_cannon", "asw_weapon_sentry_flamer", "asw_weapon_sentry_freeze", "asw_weapon_hornet_barrage", "asw_weapon_electrified_armor", "asw_weapon_flares", "asw_weapon_welder", "asw_weapon_stim", "asw_weapon_ammo_satchel", "hacking_icon", }; CASW_Hud_Master::CASW_Hud_Master( const char *pElementName ) : CASW_HudElement( pElementName ), BaseClass( NULL, "ASW_Hud_Master" ) { SetParent( GetClientMode()->GetViewport() ); SetScheme( vgui::scheme()->LoadSchemeFromFile( "resource/SwarmSchemeNew.res", "SwarmSchemeNew" ) ); ADD_HUD_SHEET( Sheet1, "vgui/hud/sheet1/sheet1" ); ADD_HUD_SHEET( Sheet_Stencil, "vgui/hud/sheet_stencil/sheet_stencil" ); for ( int i = 0; i < m_HudSheets.Count(); i++ ) { *( m_HudSheets[i].m_pSheetID ) = -1; } m_pLocalMarine = NULL; m_hLocalMarine = NULL; m_pLocalMarineResource = NULL; m_pLocalMarineProfile = NULL; m_pLocalMarineActiveWeapon = NULL; m_flLastReloadProgress = 0; m_flLastNextAttack = 0; m_flLastFastReloadStart = 0; m_flLastFastReloadEnd = 0; m_flLastHealthChangeTime = 0.0f; m_flCurHealthPercent = 1.0f; m_flPrevHealthPercent = 1.0f; m_bFading = false; } CASW_Hud_Master::~CASW_Hud_Master() { } void CASW_Hud_Master::Init() { CASW_HudElement::Init(); HOOK_HUD_MESSAGE( CASW_Hud_Master, ASWOrderUseItemFX ); HOOK_HUD_MESSAGE( CASW_Hud_Master, ASWOrderStopItemFX ); HOOK_HUD_MESSAGE( CASW_Hud_Master, ASWInvalidDesination ); } void CASW_Hud_Master::VidInit() { CASW_HudElement::VidInit(); for ( int i = 0; i < m_HudSheets.Count(); i++ ) { if ( *( m_HudSheets[i].m_pSheetID ) == -1 ) { *( m_HudSheets[i].m_pSheetID ) = surface()->CreateNewTextureID(); surface()->DrawSetTextureFile( *( m_HudSheets[i].m_pSheetID ), m_HudSheets[i].m_pszTextureFile, true, false ); // pull out UV coords for this sheet ITexture *pTexture = materials->FindTexture( m_HudSheets[i].m_pszTextureFile, TEXTURE_GROUP_VGUI ); if ( pTexture ) { m_HudSheets[i].m_pSize->x = pTexture->GetActualWidth(); m_HudSheets[i].m_pSize->y = pTexture->GetActualHeight(); size_t numBytes; void const *pSheet = pTexture->GetResourceData( VTF_RSRC_SHEET, &numBytes ); if ( pSheet ) { CUtlBuffer bufLoad( pSheet, numBytes, CUtlBuffer::READ_ONLY ); CSheet *pSheet = new CSheet( bufLoad ); for ( int k = 0; k < pSheet->m_SheetInfo.Count(); k++ ) { if ( k >= m_HudSheets[i].m_nNumSubTextures ) { break; } SequenceSampleTextureCoords_t &Coords = pSheet->m_SheetInfo[ k ].m_pSamples->m_TextureCoordData[ 0 ]; m_HudSheets[i].m_pTextureData[ k ].u = Coords.m_fLeft_U0; m_HudSheets[i].m_pTextureData[ k ].v = Coords.m_fTop_V0; m_HudSheets[i].m_pTextureData[ k ].s = Coords.m_fRight_U0; m_HudSheets[i].m_pTextureData[ k ].t = Coords.m_fBottom_V0; } } else { Warning( "Error finding VTF_RSRC_SHEET for %s\n", m_HudSheets[i].m_pszTextureFile ); } } else { Warning( "Error finding %s\n", m_HudSheets[i].m_pszTextureFile ); } } } m_LocalMarineVideo.SetLoopVideo( ASW_VIDEO_FACE_HEALTHY, 1, 0.3f ); m_nLocalMarineVideoTextureID = surface()->CreateNewTextureID( true ); g_pMatSystemSurface->DrawSetTextureMaterial( m_nLocalMarineVideoTextureID, m_LocalMarineVideo.GetMaterial() ); } void CASW_Hud_Master::ApplySchemeSettings( IScheme *scheme ) { BaseClass::ApplySchemeSettings( scheme ); } void CASW_Hud_Master::UpdatePortraitVideo() { if ( m_pLocalMarineResource ) { // TODO: Play an infested video // if ( m_pLocalMarineResource->IsInfested() ) // { // m_LocalMarineVideo.SetLoopVideo( "test_infested" ); // } // else { bool bHealthChanged = ( m_nLastLocalMarineHealth != m_nLocalMarineHealth ); if ( bHealthChanged ) { if ( m_nLocalMarineHealth < m_nLastLocalMarineHealth ) // marine has taken damage { // TODO: Do we need to add a timer so we don't restart this too often? m_LocalMarineVideo.PlayTempVideo( ASW_VIDEO_FACE_PAIN, ASW_VIDEO_FACE_STATIC ); } float flHealthPercent = m_pLocalMarineResource->GetHealthPercent(); if ( flHealthPercent < 0.5f ) { m_LocalMarineVideo.SetLoopVideo( ASW_VIDEO_FACE_NEEDHEALTH ); } else { m_LocalMarineVideo.SetLoopVideo( ASW_VIDEO_FACE_HEALTHY, 1, 0.3f ); } } } } m_nLastLocalMarineHealth = m_nLocalMarineHealth; } void CASW_Hud_Master::OnThink() { BaseClass::OnThink(); C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if ( !pPlayer || !ASWGameResource() || !ASWEquipmentList() ) return; // gather squad mate data int nMaxResources = ASWGameResource() ? ASWGameResource()->GetMaxMarineResources() : 0; int nPosition = 0; for ( int i = 0; i < nMaxResources && nPosition < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i ); if ( pMR && !( pMR->IsLocal() && pMR->IsInhabited() ) ) { CASW_Marine_Profile *pProfile = pMR->GetProfile(); C_ASW_Marine *pMarine = pMR->GetMarineEntity(); m_SquadMateInfo[ nPosition ].hMarine = pMarine; m_SquadMateInfo[ nPosition ].bPositionActive = true; m_SquadMateInfo[ nPosition ].MarineClass = pProfile->GetMarineClass(); m_SquadMateInfo[ nPosition ].nClassIcon = GetClassIcon( pMR ); m_SquadMateInfo[ nPosition ].flHealthFraction = pMR->GetHealthPercent(); m_SquadMateInfo[ nPosition ].flInfestation = pMR->GetInfestedPercent(); m_SquadMateInfo[ nPosition ].bInhabited = pMR->IsInhabited(); pMR->GetDisplayName( m_SquadMateInfo[ nPosition ].wszMarineName, sizeof( m_SquadMateInfo[ nPosition ].wszMarineName ) ); if ( pMarine ) { m_SquadMateInfo[ nPosition ].pWeapon = pMarine->GetActiveASWWeapon(); if ( m_SquadMateInfo[ nPosition ].pWeapon ) { int nTotalBullets = pMarine->GetAmmoCount( m_SquadMateInfo[ nPosition ].pWeapon->GetPrimaryAmmoType() ); int nMaxClip = m_SquadMateInfo[ nPosition ].pWeapon->GetMaxClip1(); m_SquadMateInfo[ nPosition ].nClips = nTotalBullets / nMaxClip; // TODO: Ammo bag? int nAmmoIndex = m_SquadMateInfo[ nPosition ].pWeapon->GetPrimaryAmmoType(); int nGuns = pMarine->GetNumberOfWeaponsUsingAmmo( nAmmoIndex ); int nMaxBullets = GetAmmoDef()->MaxCarry( nAmmoIndex, pMarine ) * nGuns; m_SquadMateInfo[ nPosition ].nMaxClips = nMaxBullets / nMaxClip; if ( m_SquadMateInfo[ nPosition ].pWeapon->DisplayClipsDoubled() ) { m_SquadMateInfo[ nPosition ].nClips *= 2; m_SquadMateInfo[ nPosition ].nMaxClips *= 2; } m_SquadMateInfo[ nPosition ].flAmmoFraction = pMR->GetAmmoPercent(); //Msg( "Setting squadmate %d ammo to %f. clip1 is %d max is %d\n", nPosition, pMR->GetAmmoPercent(), //m_SquadMateInfo[ nPosition ].pWeapon->Clip1(), m_SquadMateInfo[ nPosition ].pWeapon->GetMaxClip1() ); } else { m_SquadMateInfo[ nPosition ].nClips = 0; m_SquadMateInfo[ nPosition ].nMaxClips = 0; m_SquadMateInfo[ nPosition ].flAmmoFraction = 0; //Msg( "Setting squadmate %d ammo to zero 1\n", nPosition ); } // Search primary and secondary slots for a usable item first C_ASW_Weapon *( pExtraItem[ 2 ] ) = { NULL, NULL }; int nInventoryIndex[ 2 ]; int nItemCount = 0; for ( int k = 0; k < ASW_NUM_INVENTORY_SLOTS && nItemCount < 2; k++ ) { C_ASW_Weapon *pWeapon = pMarine->GetASWWeapon( k ); if ( !pWeapon ) continue; const CASW_WeaponInfo* pInfo = pWeapon->GetWeaponInfo(); if ( !pInfo || !( pInfo->m_bOffhandActivate || ( pInfo->m_bHUDPlayerActivate && pMR->IsInhabited() ) ) ) continue; pExtraItem[ nItemCount ] = pWeapon; nInventoryIndex[ nItemCount ] = k; nItemCount++; } bool bWalking = ( pPlayer->GetMarine() && pPlayer->GetMarine()->m_bWalking ); if ( bWalking ) { int poop = 1; poop = 2; } int nItemSelect = bWalking ? 1 : 0; int nItemShift = nItemSelect == 0 ? 1 : 0; if ( pExtraItem[ nItemSelect ] ) { m_SquadMateInfo[ nPosition ].pExtraItemInfo = pExtraItem[ nItemSelect ]->GetWeaponInfo(); m_SquadMateInfo[ nPosition ].nExtraItemInventoryIndex = nInventoryIndex[ nItemSelect ]; m_SquadMateInfo[ nPosition ].nEquipmentListIndex = pExtraItem[ nItemSelect ]->GetEquipmentListIndex(); m_SquadMateInfo[ nPosition ].nExtraItemQuantity = pExtraItem[ nItemSelect ]->Clip1(); } else { m_SquadMateInfo[ nPosition ].pExtraItemInfo = NULL; } if ( pExtraItem[ nItemShift ] ) { m_SquadMateInfo[ nPosition ].pExtraItemInfoShift = pExtraItem[ nItemShift ]->GetWeaponInfo(); } else { m_SquadMateInfo[ nPosition ].pExtraItemInfoShift = NULL; } } else { m_SquadMateInfo[ nPosition ].pExtraItemInfo = NULL; m_SquadMateInfo[ nPosition ].pExtraItemInfoShift = NULL; m_SquadMateInfo[ nPosition ].pWeapon = NULL; m_SquadMateInfo[ nPosition ].nClips = 0; m_SquadMateInfo[ nPosition ].flAmmoFraction = 0; //Msg( "Setting squadmate %d ammo to zero 2\n", nPosition ); } nPosition++; } } for ( int i = nPosition; i < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { m_SquadMateInfo[ i ].bPositionActive = false; } //UpdatePortraitVideo(); // loops through to see if we have effects that are flagged to die after a certain time HotbarOrderEffectsList_t::IndexLocalType_t f = m_hHotbarOrderEffects.Head(); while ( m_hHotbarOrderEffects.IsValidIndex( f ) ) { // advance before deleting the pointer out from under us const HotbarOrderEffectsList_t::IndexLocalType_t oldf = f; f = m_hHotbarOrderEffects.Next( f ); if ( m_hHotbarOrderEffects[oldf].flRemoveAtTime > 0 && m_hHotbarOrderEffects[oldf].flRemoveAtTime < gpGlobals->curtime ) { int iMarine = m_hHotbarOrderEffects[oldf].iEffectID; C_ASW_Marine *pMarine = dynamic_cast(ClientEntityList().GetEnt(iMarine)); // turn iMarine ent index into the marine if ( !pMarine ) return; StopItemFX( pMarine, -1 ); } } } void CASW_Hud_Master::Paint( void ) { VPROF_BUDGET( "CASW_Hud_Master::Paint", VPROF_BUDGETGROUP_ASW_CLIENT ); C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if ( !pPlayer ) return; // gather data for local player m_pLocalMarine = C_ASW_Marine::GetLocalMarine(); // only valid inside OnThink and Paint m_hLocalMarine = m_pLocalMarine; // take a handle copy for things like the CLocatorPanel which want to find this outside of our Paint m_pLocalMarineResource = m_pLocalMarine ? m_pLocalMarine->GetMarineResource() : ASWGameResource()->GetFirstMarineResourceForPlayer( pPlayer ); m_pLocalMarineProfile = m_pLocalMarineResource ? m_pLocalMarineResource->GetProfile() : NULL; m_pLocalMarineActiveWeapon = m_pLocalMarine ? m_pLocalMarine->GetActiveASWWeapon() : NULL; if ( m_pLocalMarineActiveWeapon ) { // clips int nTotalBullets = m_pLocalMarine->GetAmmoCount( m_pLocalMarineActiveWeapon->GetPrimaryAmmoType() ); int nMaxClip = m_pLocalMarineActiveWeapon->GetMaxClip1(); m_nLocalMarineClips = nMaxClip == 0 ? 1 : nTotalBullets / nMaxClip; // TODO: Ammo bag? int nAmmoIndex = m_pLocalMarineActiveWeapon->GetPrimaryAmmoType(); int nGuns = m_pLocalMarine->GetNumberOfWeaponsUsingAmmo( nAmmoIndex ); int nMaxBullets = GetAmmoDef()->MaxCarry( nAmmoIndex, m_pLocalMarine ) * nGuns; m_nLocalMarineMaxClips = nMaxClip == 0 ? 1 : nMaxBullets / nMaxClip; if ( m_pLocalMarineActiveWeapon->DisplayClipsDoubled() ) { m_nLocalMarineClips *= 2; } m_nLocalMarineBullets = m_pLocalMarineActiveWeapon->Clip1(); m_nLocalMarineGrenades = m_pLocalMarineActiveWeapon->Clip2(); m_nLocalMarineGrenades = MIN( m_nLocalMarineGrenades, 9 ); } else { m_nLocalMarineClips = 0; m_nLocalMarineMaxClips = 0; } if ( m_pLocalMarine ) { m_nLocalMarineHealth = m_pLocalMarine->GetHealth(); } else { m_nLocalMarineHealth = 0; } if ( m_pLocalMarineResource ) { C_ASW_Marine_Resource *pMR = m_pLocalMarineResource; float flTimeToFade = 2.0f; float flHealthPercent = pMR->GetHealthPercent(); m_flMainProgress = 0.0f; m_flDelayProgress = 0.0f; float flAlphaDelay = 225.0f; m_colorMain = Color( 255, 255, 255, 255 ); m_colorBG = Color( 255, 255, 255, 255 ); m_colorDelay = Color( 255, 255, 255, 255 ); // the Delay bar is fading or animating if ( (m_flLastHealthChangeTime + flTimeToFade) >= gpGlobals->curtime && m_bFading ) { if ( m_flCurHealthPercent < m_flPrevHealthPercent ) { float flAlpha = 225.0f; flAlpha *= clamp( ((m_flLastHealthChangeTime+flTimeToFade) - gpGlobals->curtime)/flTimeToFade, 0.0f, 225.0f ); flAlphaDelay = flAlpha; m_flMainProgress = flHealthPercent; m_flDelayProgress = m_flPrevHealthPercent; } else { float flCurProg = m_flPrevHealthPercent; flCurProg = Approach( m_flCurHealthPercent, flCurProg, (gpGlobals->curtime - m_flLastHealthChangeTime) * (m_flCurHealthPercent - m_flPrevHealthPercent) / 20.0f ); m_flMainProgress = flCurProg; m_flPrevHealthPercent = flCurProg; m_flDelayProgress = m_flCurHealthPercent; flAlphaDelay *= clamp( ((m_flLastHealthChangeTime+flTimeToFade) - gpGlobals->curtime)/flTimeToFade, 0.0f, 225.0f ); if ( flCurProg >= m_flDelayProgress - 0.01f ) m_bFading = false; } } else { m_bFading = false; m_flPrevHealthPercent = m_flCurHealthPercent; flAlphaDelay = 0; m_flMainProgress = flHealthPercent; } if ( flHealthPercent < m_flCurHealthPercent ) { m_flPrevHealthPercent = m_flCurHealthPercent; m_flCurHealthPercent = flHealthPercent; m_flLastHealthChangeTime = gpGlobals->curtime; m_flDelayProgress = m_flPrevHealthPercent; m_flMainProgress = m_flCurHealthPercent; m_bFading = true; } else if ( flHealthPercent > m_flCurHealthPercent ) { m_flPrevHealthPercent = m_flCurHealthPercent; m_flCurHealthPercent = flHealthPercent; m_flLastHealthChangeTime = gpGlobals->curtime; m_flDelayProgress = m_flCurHealthPercent; m_flMainProgress = m_flPrevHealthPercent; m_bFading = true; } // if ( m_bFading && m_flCurHealthPercent > m_flPrevHealthPercent ) // m_colorDelay = Color( 255, 240, 240, flAlphaDelay ); // else if( m_bFading && m_flCurHealthPercent < m_flPrevHealthPercent ) // m_colorDelay = Color( 255, 160, 32, flAlphaDelay ); m_colorDelay = Color( 255, 255, 255, flAlphaDelay ); if ( flHealthPercent < 0.6 ) { // pulse BG? float flSinePeriod = 2.0f; float flValue = ( sin( 2.0f * M_PI * gpGlobals->curtime / flSinePeriod ) * 0.5f ) + 0.5f; m_colorBG = Color( 255, 155.0f + 100.0f * flValue, 155.0f + 100.0f * flValue, 255); } if ( flHealthPercent < 0.33 ) { float flSinePeriod = 1.0f; float flValue = ( sin( 2.0f * M_PI * gpGlobals->curtime / flSinePeriod ) * 0.5f ) + 0.5f; m_colorBG = Color( 255, 155.0f + 100.0f * flValue, 155.0f + 100.0f * flValue, 255); } } // calculate some positions int nCurrentMarine = 0; if ( pPlayer && ASWGameResource() ) { for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ ) { C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i ); if ( pMR && pMR->GetCommander() == pPlayer ) { if ( pMR->IsInhabited() ) break; nCurrentMarine++; } } } // shift along depending on which marine we are int cursor_x = YRES( 18 ); int nSquadMate = 0; for ( int i = 0; i < 4; i++ ) { if ( i == nCurrentMarine ) { m_nMarinePortrait_x = cursor_x; cursor_x += m_nSquadMates_x; } else if ( nSquadMate < MAX_SQUADMATE_HUD_POSITIONS ) { m_SquadMateInfo[ nSquadMate ].xpos = cursor_x; cursor_x += m_nSquadMates_spacing; nSquadMate++; } } m_nMarinePortrait_circle_x = m_nMarinePortrait_x + m_nMarinePortrait_circle_bg_x; m_nMarinePortrait_circle_x2 = m_nMarinePortrait_circle_x + m_nMarinePortrait_circle_bg_w; m_nMarinePortrait_circle_y = m_nMarinePortrait_y + m_nMarinePortrait_circle_bg_y; m_nMarinePortrait_circle_y2 = m_nMarinePortrait_circle_y + m_nMarinePortrait_circle_bg_t; m_nMarinePortrait_bar_x = m_nMarinePortrait_circle_x2; m_nMarinePortrait_bar_x2 = m_nMarinePortrait_bar_x + m_nMarinePortrait_bar_bg_w; m_nMarinePortrait_bar_y = m_nMarinePortrait_circle_y + m_nMarinePortrait_circle_bg_t * 0.5f; m_nMarinePortrait_bar_y2 = m_nMarinePortrait_circle_y2; if ( m_pLocalMarineProfile && m_pLocalMarineResource ) { PaintLocalMarinePortrait(); PaintLocalMarineInventory(); PaintFastReload(); } for ( int i = 0; i < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { if ( m_SquadMateInfo[ i ].bPositionActive ) { PaintSquadMemberStatus( i ); } } PaintSquadMatesInventory(); // paint text PaintText(); for ( int i = 0; i < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { if ( m_SquadMateInfo[ i ].bPositionActive ) { PaintSquadMemberText( i ); } } } bool CASW_Hud_Master::LookupElementBounds( const char *elementName, int &x, int &y, int &wide, int &tall ) { if ( !elementName || !m_hLocalMarine.Get() ) return false; if ( V_strcmp( elementName, "weapon1" ) == 0 ) { Assert( ASWEquipmentList() ); CASW_Weapon *pWeapon = m_hLocalMarine->GetASWWeapon( ASW_INVENTORY_SLOT_SECONDARY ); if ( pWeapon ) { const CASW_WeaponInfo *pInfo = pWeapon->GetWeaponInfo(); x = YRES( pInfo->m_iHUDIconOffsetX ) + m_nSecondaryWeapon_x; y = YRES( pInfo->m_iHUDIconOffsetY ) + m_nSecondaryWeapon_y; wide = m_nWeapon_w; tall = m_nWeapon_t; } } else if ( V_strcmp( elementName, "squadpanel0" ) == 0 ) { Assert( ASWEquipmentList() ); CASW_Weapon *pWeapon = m_hLocalMarine->GetASWWeapon( ASW_INVENTORY_SLOT_EXTRA ); if ( pWeapon ) { x = m_nExtraItem_x + m_nMarinePortrait_x; y = m_nExtraItem_y + m_nMarinePortrait_y; wide = m_nWeapon_w; tall = m_nWeapon_t; } } else if ( StringHasPrefix( elementName, "squadpanel" ) ) { int nPanel = atoi( elementName + 10 ) - 1; if ( nPanel < 0 && nPanel >= MAX_SQUADMATE_HUD_POSITIONS ) { return false; } if ( m_SquadMateInfo[ nPanel ].hMarine.Get() == NULL ) { return false; } CASW_Weapon *pWeapon = m_SquadMateInfo[ nPanel ].hMarine->GetASWWeapon( ASW_INVENTORY_SLOT_EXTRA ); if ( !pWeapon ) { return false; } if ( pWeapon ) { x = m_SquadMateInfo[ nPanel ].xpos; y = m_nSquadMates_y; x += m_nSquadMate_ExtraItem_x; y += m_nSquadMate_ExtraItem_y; wide = m_nSquadMate_ExtraItem_w; tall = m_nSquadMate_ExtraItem_t; } } else if ( V_strcmp( elementName, "altammo" ) == 0 ) { x = m_nMarinePortrait_x + m_nMarinePortrait_grenades_icon_x; y = m_nMarinePortrait_y + m_nMarinePortrait_grenades_icon_y; wide = m_nMarinePortrait_grenades_icon_w; tall = m_nMarinePortrait_grenades_icon_t; } else { return false; } return true; } int CASW_Hud_Master::GetClassIcon( C_ASW_Marine_Resource *pMR ) { int nUV = UV_NCOClassIcon; if ( pMR->GetHealthPercent() <= 0.0f ) { nUV = UV_DeadIcon; } else if ( pMR->IsInfested() ) { nUV = UV_InfestedIcon; } else { switch ( pMR->GetProfile()->GetMarineClass() ) { case MARINE_CLASS_SPECIAL_WEAPONS: nUV = UV_SpecialWeaponsClassIcon; break; case MARINE_CLASS_MEDIC: nUV = UV_MedicClassIcon; break; case MARINE_CLASS_TECH: nUV = UV_TechClassIcon; break; } } return nUV; } void CASW_Hud_Master::PaintLocalMarinePortrait() { surface()->DrawSetTexture( m_nSheet1ID ); // backgrounds surface()->DrawSetColor( 255, 255, 255, asw_hud_alpha.GetInt() ); surface()->DrawTexturedSubRect( m_nMarinePortrait_circle_x, m_nMarinePortrait_circle_y, m_nMarinePortrait_circle_x2, m_nMarinePortrait_circle_y2, HUD_UV_COORDS( Sheet1, UV_marine_portrait_BG_circle ) ); float flSheet1HalfPixel_x = 1.0f / m_vecSheet1Size.x; float flSheet1HalfPixel_y = 1.0f / m_vecSheet1Size.y; vgui::Vertex_t portrait_bar_points[4] = { vgui::Vertex_t( Vector2D(m_nMarinePortrait_bar_x, m_nMarinePortrait_bar_y), Vector2D(m_Sheet1[ UV_marine_portrait_square ].u + flSheet1HalfPixel_x, m_Sheet1[ UV_marine_portrait_square ].v + flSheet1HalfPixel_y) ), vgui::Vertex_t( Vector2D(m_nMarinePortrait_bar_x2, m_nMarinePortrait_bar_y), Vector2D(m_Sheet1[ UV_marine_portrait_square ].s - flSheet1HalfPixel_x, m_Sheet1[ UV_marine_portrait_square ].v + flSheet1HalfPixel_y) ), vgui::Vertex_t( Vector2D(m_nMarinePortrait_bar_x2, m_nMarinePortrait_bar_y2), Vector2D(m_Sheet1[ UV_marine_portrait_square ].s - flSheet1HalfPixel_x, m_Sheet1[ UV_marine_portrait_square ].t - flSheet1HalfPixel_y) ), vgui::Vertex_t( Vector2D(m_nMarinePortrait_bar_x, m_nMarinePortrait_bar_y2), Vector2D(m_Sheet1[ UV_marine_portrait_square ].u + flSheet1HalfPixel_x, m_Sheet1[ UV_marine_portrait_square ].t - flSheet1HalfPixel_y) ) }; vgui::surface()->DrawTexturedPolygon( 4, portrait_bar_points ); // need to material switch to draw the video here //m_LocalMarineVideo.Update(); //g_pMatSystemSurface->DrawSetTextureMaterial( m_nLocalMarineVideoTextureID, m_LocalMarineVideo.GetMaterial() ); surface()->DrawSetTexture( m_pLocalMarineProfile->m_nPortraitTextureID ); surface()->DrawSetColor( 255, 255, 255, 255 ); const int NUM_CIRCLE_POINTS = 32; vgui::Vertex_t portrait_points[ NUM_CIRCLE_POINTS ]; for ( int i = 0; i < NUM_CIRCLE_POINTS; i++ ) { float flAngle = 2.0f * M_PI * i / NUM_CIRCLE_POINTS; portrait_points[i].m_Position.x = m_nMarinePortrait_x + m_nMarinePortrait_face_x + cos( flAngle ) * m_nMarinePortrait_face_radius; portrait_points[i].m_Position.y = m_nMarinePortrait_y + m_nMarinePortrait_face_y + sin( flAngle ) * m_nMarinePortrait_face_radius; portrait_points[i].m_TexCoord.x = 0.5f + cos( flAngle ) * 0.5f; portrait_points[i].m_TexCoord.y = 0.5f + sin( flAngle ) * 0.5f; } vgui::surface()->DrawTexturedPolygon( NUM_CIRCLE_POINTS, portrait_points ); surface()->DrawSetTexture( m_nSheet1ID ); // health bar background surface()->DrawSetColor( m_colorBG ); surface()->DrawTexturedSubRect( m_nMarinePortrait_circle_x, m_nMarinePortrait_circle_y, m_nMarinePortrait_circle_x2, m_nMarinePortrait_circle_y2, HUD_UV_COORDS( Sheet1, UV_marine_health_circle_BG ) ); float flHealthFraction = m_pLocalMarineResource->GetHealthPercent(); // draw recent damage surface()->DrawSetColor( m_colorDelay ); ASWCircularProgressBar::DrawCircleSegmentAtPosition( m_nMarinePortrait_circle_x + m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_y + m_nMarinePortrait_circle_bg_t * 0.5f, m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_bg_t * 0.5f, 0.75f * ( m_flMainProgress ), 0.75f * ( m_flDelayProgress ), true, 180, -180, HUD_UV_COORDS( Sheet1, UV_marine_health_circle_FG_subtract ) ); // draw infestation if ( m_pLocalMarineResource->IsInfested() ) { float flInfestation = m_pLocalMarineResource->GetInfestedPercent(); flInfestation = clamp( flInfestation, 0.0f, flHealthFraction ); surface()->DrawSetColor( Color( 255, 255, 255, 255 ) ); ASWCircularProgressBar::DrawCircleSegmentAtPosition( m_nMarinePortrait_circle_x + m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_y + m_nMarinePortrait_circle_bg_t * 0.5f, m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_bg_t * 0.5f, flInfestation * 0.75f, ( flHealthFraction * 0.75f ), true, 180, -180, HUD_UV_COORDS( Sheet1, UV_marine_health_circle_FG_infested ) ); // draw uninfested health bar float flUninfestedHealth = flHealthFraction - flInfestation; if ( flUninfestedHealth > 0.0f ) { surface()->DrawSetColor( Color( 255, 255, 255, 255 ) ); ASWCircularProgressBar::DrawCircleSegmentAtPosition( m_nMarinePortrait_circle_x + m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_y + m_nMarinePortrait_circle_bg_t * 0.5f, m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_bg_t * 0.5f, 0, flUninfestedHealth * 0.75f, true, 180, -180, HUD_UV_COORDS( Sheet1, UV_marine_health_circle_FG ) ); } } else { // draw health bar surface()->DrawSetColor( Color( 255, 255, 255, 255 ) ); ASWCircularProgressBar::DrawCircleSegmentAtPosition( m_nMarinePortrait_circle_x + m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_y + m_nMarinePortrait_circle_bg_t * 0.5f, m_nMarinePortrait_circle_bg_w * 0.5f, m_nMarinePortrait_circle_bg_t * 0.5f, 0, flHealthFraction * 0.75f, true, 180, -180, HUD_UV_COORDS( Sheet1, UV_marine_health_circle_FG ) ); } // class icon/special status surface()->DrawSetColor( 255, 255, 255, 255 ); surface()->DrawTexturedSubRect( m_nMarinePortrait_x + m_nMarinePortrait_class_icon_x, m_nMarinePortrait_y + m_nMarinePortrait_class_icon_y, m_nMarinePortrait_x + m_nMarinePortrait_class_icon_x + m_nMarinePortrait_class_icon_w, m_nMarinePortrait_y + m_nMarinePortrait_class_icon_y + m_nMarinePortrait_class_icon_t, HUD_UV_COORDS( Sheet1, GetClassIcon( m_pLocalMarineResource ) ) ); if ( m_pLocalMarineActiveWeapon ) { const CASW_WeaponInfo *pInfo = m_pLocalMarineActiveWeapon->GetWeaponInfo(); surface()->DrawSetTexture( m_nSheet_StencilID ); if ( pInfo->m_iShowBulletsOnHUD ) { surface()->DrawTexturedSubRect( m_nMarinePortrait_x + m_nMarinePortrait_bullets_icon_x, m_nMarinePortrait_y + m_nMarinePortrait_bullets_icon_y, m_nMarinePortrait_x + m_nMarinePortrait_bullets_icon_x + m_nMarinePortrait_bullets_icon_w, m_nMarinePortrait_y + m_nMarinePortrait_bullets_icon_y + m_nMarinePortrait_bullets_icon_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_bullets ) ); } if ( pInfo->m_iShowGrenadesOnHUD ) { surface()->DrawTexturedSubRect( m_nMarinePortrait_x + m_nMarinePortrait_grenades_icon_x, m_nMarinePortrait_y + m_nMarinePortrait_grenades_icon_y, m_nMarinePortrait_x + m_nMarinePortrait_grenades_icon_x + m_nMarinePortrait_grenades_icon_w, m_nMarinePortrait_y + m_nMarinePortrait_grenades_icon_y + m_nMarinePortrait_grenades_icon_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_grenade ) ); } if ( pInfo->m_iShowClipsOnHUD ) { if ( m_nLocalMarineClips > 5 ) { // just draw one clip icon, the quantity will be drawn as text surface()->DrawTexturedSubRect( m_nMarinePortrait_x + m_nMarinePortrait_clips_x, m_nMarinePortrait_y + m_nMarinePortrait_clips_y, m_nMarinePortrait_x + m_nMarinePortrait_clips_x + m_nMarinePortrait_clips_w, m_nMarinePortrait_y + m_nMarinePortrait_clips_y + m_nMarinePortrait_clips_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_clip_full ) ); } else { // draw up to 5 clip icons, filling them in if the player has that many clips for ( int i = 0; i < 5; i++ ) { int x = m_nMarinePortrait_x + m_nMarinePortrait_clips_x + m_nMarinePortrait_spacing * i; if ( m_nLocalMarineClips > i ) { surface()->DrawSetColor( 255, 255, 255, 255 ); surface()->DrawTexturedSubRect( x, m_nMarinePortrait_y + m_nMarinePortrait_clips_y, x + m_nMarinePortrait_clips_w, m_nMarinePortrait_y + m_nMarinePortrait_clips_y + m_nMarinePortrait_clips_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_clip_full ) ); } else if ( m_nLocalMarineMaxClips > i ) { surface()->DrawSetColor( 128, 128, 128, 255 ); surface()->DrawTexturedSubRect( x, m_nMarinePortrait_y + m_nMarinePortrait_clips_y, x + m_nMarinePortrait_clips_w, m_nMarinePortrait_y + m_nMarinePortrait_clips_y + m_nMarinePortrait_clips_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_clip_empty ) ); } } } } } } void CASW_Hud_Master::PaintSquadMemberStatus( int nPosition ) { int x = m_SquadMateInfo[ nPosition].xpos; //m_nSquadMates_x + nPosition * m_nSquadMates_spacing; int y = m_nSquadMates_y; // background surface()->DrawSetColor( 255, 255, 255, asw_hud_alpha.GetInt() ); surface()->DrawSetTexture( m_nSheet1ID ); surface()->DrawTexturedSubRect( x + m_nSquadMate_bg_x, y + m_nSquadMate_bg_y, x + m_nSquadMate_bg_x + m_nSquadMate_bg_w, y + m_nSquadMate_bg_y + m_nSquadMate_bg_t, HUD_UV_COORDS( Sheet1, UV_team_portrait_BG ) ); // class icon/special status surface()->DrawSetColor( 255, 255, 255, 255 ); surface()->DrawTexturedSubRect( x + m_nSquadMate_class_icon_x, y + m_nSquadMate_class_icon_y, x + m_nSquadMate_class_icon_x + m_nSquadMate_class_icon_w, y + m_nSquadMate_class_icon_y + m_nSquadMate_class_icon_t, HUD_UV_COORDS( Sheet1, m_SquadMateInfo[ nPosition ].nClassIcon ) ); // TODO: show infested progress // TODO: Flash health bar when they get hit float health_x = x + m_nSquadMate_health_x; float health_y = y + m_nSquadMate_health_y; float health_x2 = x + m_nSquadMate_health_x + m_nSquadMate_health_w; float health_x2_progress = x + m_nSquadMate_health_x + m_nSquadMate_health_w * m_SquadMateInfo[ nPosition ].flHealthFraction; float health_y2 = y + m_nSquadMate_health_y + m_nSquadMate_health_t; vgui::Vertex_t health_bg_points[4] = { vgui::Vertex_t( Vector2D(health_x, health_y), Vector2D(m_Sheet1[ UV_team_health_bar_BG ].u, m_Sheet1[ UV_team_health_bar_BG ].v) ), vgui::Vertex_t( Vector2D(health_x2, health_y), Vector2D(m_Sheet1[ UV_team_health_bar_BG ].s, m_Sheet1[ UV_team_health_bar_BG ].v) ), vgui::Vertex_t( Vector2D(health_x2, health_y2), Vector2D(m_Sheet1[ UV_team_health_bar_BG ].s, m_Sheet1[ UV_team_health_bar_BG ].t) ), vgui::Vertex_t( Vector2D(health_x, health_y2), Vector2D(m_Sheet1[ UV_team_health_bar_BG ].u, m_Sheet1[ UV_team_health_bar_BG ].t) ) }; vgui::surface()->DrawTexturedPolygon( 4, health_bg_points ); float flHealth_UV_x2 = m_Sheet1[ UV_team_health_bar_FG ].u + (m_Sheet1[ UV_team_health_bar_FG ].s - m_Sheet1[ UV_team_health_bar_FG ].u ) * m_SquadMateInfo[ nPosition ].flHealthFraction; vgui::Vertex_t health_fg_points[4] = { vgui::Vertex_t( Vector2D(health_x, health_y), Vector2D(m_Sheet1[ UV_team_health_bar_FG ].u, m_Sheet1[ UV_team_health_bar_FG ].v) ), vgui::Vertex_t( Vector2D(health_x2_progress, health_y), Vector2D(flHealth_UV_x2, m_Sheet1[ UV_team_health_bar_FG ].v) ), vgui::Vertex_t( Vector2D(health_x2_progress, health_y2),Vector2D(flHealth_UV_x2, m_Sheet1[ UV_team_health_bar_FG ].t) ), vgui::Vertex_t( Vector2D(health_x, health_y2), Vector2D(m_Sheet1[ UV_team_health_bar_FG ].u, m_Sheet1[ UV_team_health_bar_FG ].t) ) }; vgui::surface()->DrawTexturedPolygon( 4, health_fg_points ); if ( m_SquadMateInfo[ nPosition ].flInfestation > 0.0f ) { float flInfestStart = m_SquadMateInfo[ nPosition ].flHealthFraction - m_SquadMateInfo[ nPosition ].flInfestation; flInfestStart = clamp( flInfestStart, 0.0f, m_SquadMateInfo[ nPosition ].flHealthFraction ); float infest_start_x = x + m_nSquadMate_health_x + m_nSquadMate_health_w * flInfestStart; float infest_start_UV_x = m_Sheet1[ UV_team_health_bar_FG_infested ].u + (m_Sheet1[ UV_team_health_bar_FG_infested ].s - m_Sheet1[ UV_team_health_bar_FG_infested ].u ) * flInfestStart; float infest_end_UV_x = m_Sheet1[ UV_team_health_bar_FG_infested ].u + (m_Sheet1[ UV_team_health_bar_FG_infested ].s - m_Sheet1[ UV_team_health_bar_FG_infested ].u ) * m_SquadMateInfo[ nPosition ].flHealthFraction; vgui::Vertex_t infest_fg_points[4] = { vgui::Vertex_t( Vector2D(infest_start_x, health_y), Vector2D(infest_start_UV_x, m_Sheet1[ UV_team_health_bar_FG_infested ].v) ), vgui::Vertex_t( Vector2D(health_x2_progress, health_y), Vector2D(infest_end_UV_x, m_Sheet1[ UV_team_health_bar_FG_infested ].v) ), vgui::Vertex_t( Vector2D(health_x2_progress, health_y2),Vector2D(infest_end_UV_x, m_Sheet1[ UV_team_health_bar_FG_infested ].t) ), vgui::Vertex_t( Vector2D(infest_start_x, health_y2), Vector2D(infest_start_UV_x, m_Sheet1[ UV_team_health_bar_FG_infested ].t) ) }; vgui::surface()->DrawTexturedPolygon( 4, infest_fg_points ); } C_ASW_Weapon *pWeapon = m_SquadMateInfo[ nPosition ].pWeapon; if ( pWeapon ) { surface()->DrawSetTexture( m_nSheet_StencilID ); surface()->DrawSetColor( m_SquadMate_bullets_bg_color ); float bullets_x = x + m_nSquadMate_bullets_x; float bullets_y = y + m_nSquadMate_bullets_y; float bullets_x2 = x + m_nSquadMate_bullets_x + m_nSquadMate_bullets_w; float bullets_x2_progress = x + m_nSquadMate_bullets_x + m_nSquadMate_bullets_w * m_SquadMateInfo[ nPosition ].flAmmoFraction; float bullets_y2 = y + m_nSquadMate_bullets_y + m_nSquadMate_bullets_t; vgui::Vertex_t bullets_bg_points[4] = { vgui::Vertex_t( Vector2D(bullets_x, bullets_y), Vector2D(m_Sheet_Stencil[ UV_team_ammo_bar ].u, m_Sheet_Stencil[ UV_team_ammo_bar ].v) ), vgui::Vertex_t( Vector2D(bullets_x2, bullets_y), Vector2D(m_Sheet_Stencil[ UV_team_ammo_bar ].s, m_Sheet_Stencil[ UV_team_ammo_bar ].v) ), vgui::Vertex_t( Vector2D(bullets_x2, bullets_y2), Vector2D(m_Sheet_Stencil[ UV_team_ammo_bar ].s, m_Sheet_Stencil[ UV_team_ammo_bar ].t) ), vgui::Vertex_t( Vector2D(bullets_x, bullets_y2), Vector2D(m_Sheet_Stencil[ UV_team_ammo_bar ].u, m_Sheet_Stencil[ UV_team_ammo_bar ].t) ) }; vgui::surface()->DrawTexturedPolygon( 4, bullets_bg_points ); surface()->DrawSetColor( m_SquadMate_bullets_fg_color ); // TODO: Flash this after they fire float flUV_x2 = m_Sheet_Stencil[ UV_team_ammo_bar ].u + (m_Sheet_Stencil[ UV_team_ammo_bar ].s - m_Sheet_Stencil[ UV_team_ammo_bar ].u ) * m_SquadMateInfo[ nPosition ].flAmmoFraction; vgui::Vertex_t bullets_points[4] = { vgui::Vertex_t( Vector2D(bullets_x, bullets_y), Vector2D(m_Sheet_Stencil[ UV_team_ammo_bar ].u, m_Sheet_Stencil[ UV_team_ammo_bar ].v) ), vgui::Vertex_t( Vector2D(bullets_x2_progress, bullets_y), Vector2D(flUV_x2, m_Sheet_Stencil[ UV_team_ammo_bar ].v) ), vgui::Vertex_t( Vector2D(bullets_x2_progress, bullets_y2), Vector2D(flUV_x2, m_Sheet_Stencil[ UV_team_ammo_bar ].t) ), vgui::Vertex_t( Vector2D(bullets_x, bullets_y2), Vector2D(m_Sheet_Stencil[ UV_team_ammo_bar ].u, m_Sheet_Stencil[ UV_team_ammo_bar ].t) ) }; vgui::surface()->DrawTexturedPolygon( 4, bullets_points ); if ( m_SquadMateInfo[ nPosition ].nClips > 5 ) { // just draw one clip icon, the quantity will be drawn as text surface()->DrawSetColor( m_SquadMate_clips_full_color ); surface()->DrawTexturedSubRect( x + m_nSquadMate_clips_x, y + m_nSquadMate_clips_y, x + m_nSquadMate_clips_x + m_nSquadMate_clips_w, y + m_nSquadMate_clips_y + m_nSquadMate_clips_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_clip_full ) ); } else { // draw up to 5 clip icons, filling them in if the player has that many clips for ( int i = 0; i < 5; i++ ) { int clip_x = x + m_nSquadMate_clips_x + m_nSquadMate_clips_spacing * i; if ( m_SquadMateInfo[ nPosition ].nClips > i ) { surface()->DrawSetColor( m_SquadMate_clips_full_color ); surface()->DrawTexturedSubRect( clip_x, y + m_nSquadMate_clips_y, clip_x + m_nSquadMate_clips_w, y + m_nSquadMate_clips_y + m_nSquadMate_clips_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_clip_full ) ); } else if ( m_SquadMateInfo[ nPosition ].nMaxClips > i ) { surface()->DrawSetColor( m_SquadMate_clips_empty_color ); surface()->DrawTexturedSubRect( clip_x, y + m_nSquadMate_clips_y, clip_x + m_nSquadMate_clips_w, y + m_nSquadMate_clips_y + m_nSquadMate_clips_t, HUD_UV_COORDS( Sheet_Stencil, UV_hud_ammo_clip_empty ) ); } } } } } void CASW_Hud_Master::PaintLocalMarineInventory() { Assert( ASWEquipmentList() ); if ( !m_pLocalMarine ) return; for ( int i = ASW_INVENTORY_SLOT_PRIMARY; i <= ASW_INVENTORY_SLOT_EXTRA; i++ ) { CASW_Weapon *pWeapon = m_pLocalMarine->GetASWWeapon( i ); if ( pWeapon ) { const CASW_WeaponInfo *pInfo = pWeapon->GetWeaponInfo(); if ( pWeapon == m_pLocalMarineActiveWeapon ) { surface()->DrawSetColor( 255, 255, 255, 255 ); } else { surface()->DrawSetColor( 66, 142, 192, 255 ); // light blue } surface()->DrawSetTexture( ASWEquipmentList()->GetEquipIconTexture( !pInfo->m_bExtra, pWeapon->GetEquipmentListIndex() ) ); int x = YRES( pInfo->m_iHUDIconOffsetX ); int y = YRES( pInfo->m_iHUDIconOffsetY ); int w = m_nWeapon_w; int t = m_nWeapon_t; switch( i ) { case ASW_INVENTORY_SLOT_PRIMARY: { x += m_nPrimaryWeapon_x; y += m_nPrimaryWeapon_y; break; } case ASW_INVENTORY_SLOT_SECONDARY: { x += m_nSecondaryWeapon_x; y += m_nSecondaryWeapon_y; break; } case ASW_INVENTORY_SLOT_EXTRA: { x = m_nExtraItem_x + m_nMarinePortrait_x; y = m_nExtraItem_y + m_nMarinePortrait_y; w = m_nExtraItem_w; t = m_nExtraItem_t; break; } } // darken icon if we can't use the item right now if ( pInfo->m_bShowBatteryCharge && pWeapon->GetBatteryCharge() < pWeapon->GetMinBatteryChargeToActivate() ) { surface()->DrawSetColor( 33, 71, 96, 192 ); } surface()->DrawTexturedRect( x, y, x + w, y + t ); if ( pInfo->m_bShowBatteryCharge ) { x += m_nExtraItem_battery_x; y += m_nExtraItem_battery_y; w = m_nExtraItem_battery_w; t = m_nExtraItem_battery_t; float flCharge = pWeapon->GetBatteryCharge(); surface()->DrawOutlinedRect( x, y, x + w, y + t ); // inset by 2 pixels x += 2; y += 2; w = ( w - 4 ) * flCharge; t -= 4; surface()->DrawFilledRect( x, y, x + w, y + t ); } // TODO: Powered up // TODO: Weapon swaps } } } void CASW_Hud_Master::PaintSquadMatesInventory() { for ( int i = 0; i < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { if ( m_SquadMateInfo[ i ].bPositionActive && m_SquadMateInfo[ i ].pExtraItemInfo ) { int x = m_SquadMateInfo[ i ].xpos; //m_nSquadMates_x + i * m_nSquadMates_spacing; int y = m_nSquadMates_y; surface()->DrawSetColor( 66, 142, 192, 255 ); x += m_nSquadMate_ExtraItem_x;// + YRES( m_SquadMateInfo[ i ].pExtraItemInfo->m_iHUDIconOffsetX ); y += m_nSquadMate_ExtraItem_y;// + YRES( m_SquadMateInfo[ i ].pExtraItemInfo->m_iHUDIconOffsetY ); int w = m_nSquadMate_ExtraItem_w; int h = m_nSquadMate_ExtraItem_t; surface()->DrawSetTexture( ASWEquipmentList()->GetEquipIconTexture( !m_SquadMateInfo[ i ].pExtraItemInfo->m_bExtra, m_SquadMateInfo[ i ].nEquipmentListIndex ) ); if ( m_SquadMateInfo[ i ].pExtraItemInfo->m_bZoomHotbarIcon ) { vgui::Vertex_t zoomed_hotbar_icon_points[4] = { vgui::Vertex_t( Vector2D(x, y), Vector2D( 0.3f, 0.1f ) ), vgui::Vertex_t( Vector2D(x + w, y), Vector2D( 0.7f, 0.1f ) ), vgui::Vertex_t( Vector2D(x + w, y + h), Vector2D( 0.7f, 0.9f ) ), vgui::Vertex_t( Vector2D(x, y + h), Vector2D( 0.3f, 0.9f ) ) }; vgui::surface()->DrawTexturedPolygon( 4, zoomed_hotbar_icon_points ); } else { if ( !m_SquadMateInfo[ i ].pExtraItemInfo->m_bExtra ) { x -= w * 0.5f; w *= 2; w *= 0.7f; h *= 0.7f; x += w * 0.2f; y += w * 0.1f; } surface()->DrawTexturedRect( x, y, x + w, y + h ); } // TODO: Powered up // TODO: Weapon swaps } } } void CASW_Hud_Master::PaintFastReload() { if ( !m_pLocalMarineActiveWeapon || !m_pLocalMarineActiveWeapon->IsReloading() ) return; // calc fast reload amounts C_ASW_Weapon *pWeapon = m_pLocalMarineActiveWeapon; float flBGAlpha = 255.0f; Color colorBG = Color( 32, 32, 32, flBGAlpha ); Color colorWindow = Color( 170, 170, 170, 255 ); Color colorBar = Color( 255, 255, 255, 255 ); float flAlphaFade = 1.0f; bool bFailure = pWeapon->m_bFastReloadFailure; bool bSuccess = pWeapon->m_bFastReloadSuccess; float fStart = pWeapon->m_fReloadStart; if ( !bFailure && !bSuccess ) { m_flLastNextAttack = pWeapon->m_flNextPrimaryAttack; } float fTotalTime = m_flLastNextAttack - fStart; if (fTotalTime <= 0) fTotalTime = 0.1f; float flProgress = 0.0f; // if we're in single player, the progress code in the weapon doesn't run on the client because we aren't predicting if ( !cl_predict->GetInt() ) flProgress = (gpGlobals->curtime - fStart) / fTotalTime; else flProgress = pWeapon->m_fReloadProgress; flProgress = MIN( flProgress, 1.0f ); if ( !bFailure && !bSuccess ) { m_flLastReloadProgress = flProgress; m_flLastFastReloadStart = ((pWeapon->m_fFastReloadStart - fStart) / fTotalTime)+0.015f; m_flLastFastReloadEnd = ((pWeapon->m_fFastReloadEnd - fStart) / fTotalTime)-0.015f; } //Msg( "C: %f - %f - %f Reload Progress = %f\n", gpGlobals->curtime, fFastStart, fFastEnd, flProgress ); if ( bFailure ) { flBGAlpha = 255.0f; if ( flProgress > 0.75f ) flAlphaFade = (1.0f - flProgress) / 0.25f; colorBG = Color( 128, 32, 16, flBGAlpha * flAlphaFade ); colorWindow = Color( 200, 128, 128, 250 * flAlphaFade ); colorBar = Color( 255, 255, 255, 255 * flAlphaFade ); } else if ( bSuccess ) { flAlphaFade = 1.0f - flProgress; colorBG = Color( 170, 170, 170, flBGAlpha * flAlphaFade ); colorWindow = Color( 190, 220, 190, 255 * flAlphaFade ); colorBar = Color( 255, 255, 255, 255 * flAlphaFade ); } int alpha = flBGAlpha * flAlphaFade; // for now, use the white texture // draw outline int x = m_nFastReload_x; int y = m_nFastReload_y; int x2 = m_nFastReload_x + m_nFastReload_w; int y2 = m_nFastReload_y + m_nFastReload_t; surface()->DrawSetColor( 255, 255, 255, alpha ); surface()->DrawOutlinedRect( x - 1, y - 1, x2 + 1, y2 + 1 ); // draw background surface()->DrawSetColor( colorBG ); surface()->DrawFilledRect( x, y, x2, y2 ); // draw fast section surface()->DrawSetColor( colorWindow ); surface()->DrawFilledRect( x + m_nFastReload_w * m_flLastFastReloadStart, y + 2, x + m_nFastReload_w * m_flLastFastReloadEnd, y2 - 2 ); // draw progress float flDrawProgress = MAX( m_flLastReloadProgress - 0.01f, 0 ); surface()->DrawSetColor( colorBar ); surface()->DrawFilledRect( x + m_nFastReload_w * flDrawProgress, y + 1, x + m_nFastReload_w * flDrawProgress + m_nFastReload_w * 0.01f, y2 - 1 ); } void CASW_Hud_Master::PaintText() { // local player portrait text: if ( m_pLocalMarineActiveWeapon && m_pLocalMarineResource ) { const CASW_WeaponInfo *pInfo = m_pLocalMarineActiveWeapon->GetWeaponInfo(); // weapon name surface()->DrawSetTextFont( m_hDefaultSmallFont ); surface()->DrawSetTextColor( 255, 255, 255, 255 ); surface()->DrawSetTextPos( m_nMarinePortrait_x + m_nMarinePortrait_weapon_name_x, m_nMarinePortrait_y + m_nMarinePortrait_weapon_name_y ); surface()->DrawUnicodeString( g_pVGuiLocalize->FindSafe( pInfo->szPrintName ) ); // > 5 clips static wchar_t wszBullets[ 6 ]; if ( pInfo->m_iShowClipsOnHUD && m_nLocalMarineClips > 5 ) { _snwprintf( wszBullets, sizeof( wszBullets ), L"x%d", m_nLocalMarineClips ); surface()->DrawSetTextPos( m_nMarinePortrait_x + m_nMarinePortrait_clips_x + m_nMarinePortrait_clips_w, m_nMarinePortrait_y + m_nMarinePortrait_clips_y ); surface()->DrawUnicodeString( wszBullets ); } // low ammo if ( ( int( gpGlobals->curtime*4 ) % 2 ) == 0 ) { bool bReloading = ( m_pLocalMarineActiveWeapon && m_pLocalMarineActiveWeapon->IsReloading() ); if ( !bReloading ) { if ( m_pLocalMarineResource->GetAmmoPercent() <= 0 ) { surface()->DrawSetTextColor( 200, 25, 25, 255 ); surface()->DrawSetTextPos( m_nMarinePortrait_x + m_nMarinePortrait_low_ammo_x, m_nMarinePortrait_y + m_nMarinePortrait_low_ammo_y ); surface()->DrawUnicodeString( g_pVGuiLocalize->FindSafe( "#asw_no_ammo" ) ); } else if ( m_pLocalMarineResource->IsLowAmmo() ) { surface()->DrawSetTextColor( 200, 25, 25, 255 ); surface()->DrawSetTextPos( m_nMarinePortrait_x + m_nMarinePortrait_low_ammo_x, m_nMarinePortrait_y + m_nMarinePortrait_low_ammo_y ); surface()->DrawUnicodeString( g_pVGuiLocalize->FindSafe( "#asw_low_ammo" ) ); } } } // Bullet count also blinks the low ammo color if set above surface()->DrawSetTextFont( m_hDefaultLargeFont ); if ( pInfo->m_iShowBulletsOnHUD ) { _snwprintf( wszBullets, sizeof( wszBullets ), L"%03d", m_nLocalMarineBullets ); surface()->DrawSetTextPos( m_nMarinePortrait_x + m_nMarinePortrait_bullets_x, m_nMarinePortrait_y + m_nMarinePortrait_bullets_y ); surface()->DrawUnicodeString( wszBullets ); } // Back to white surface()->DrawSetTextColor( 255, 255, 255, 255 ); if ( pInfo->m_iShowGrenadesOnHUD ) { _snwprintf( wszBullets, sizeof( wszBullets ), L"%d", m_nLocalMarineGrenades ); surface()->DrawSetTextPos( m_nMarinePortrait_x + m_nMarinePortrait_grenades_x, m_nMarinePortrait_y + m_nMarinePortrait_grenades_y ); surface()->DrawUnicodeString( wszBullets ); } } CASW_Weapon *pExtraItem = m_pLocalMarine ? m_pLocalMarine->GetASWWeapon( ASW_INVENTORY_SLOT_EXTRA ) : NULL; if ( pExtraItem ) { int w, t; // quantity for extra item if ( pExtraItem->GetWeaponInfo() ) { if ( pExtraItem->GetWeaponInfo()->m_bShowCharges ) { wchar_t wszQuantity[ 12 ]; _snwprintf( wszQuantity, sizeof( wszQuantity ), L"x%d", pExtraItem->Clip1() ); surface()->DrawSetTextColor( m_SquadMate_ExtraItem_quantity_color ); surface()->DrawSetTextFont( m_hDefaultSmallFont ); surface()->GetTextSize( m_hDefaultSmallFont, wszQuantity, w, t ); surface()->DrawSetTextPos( m_nExtraItem_quantity_x + m_nMarinePortrait_x - w, m_nExtraItem_quantity_y + m_nMarinePortrait_y - t ); surface()->DrawUnicodeString( wszQuantity ); } if ( pExtraItem->GetWeaponInfo()->m_bShowLocalPlayerHotkey ) { // show hotkey for this marine's extra item const char *pszKey = ASW_FindKeyBoundTo( "+grenade1" ); if ( pszKey ) { wchar_t wszKey[ 12 ]; wchar_t *pwchKeyName = g_pVGuiLocalize->Find( pszKey ); if ( !pwchKeyName || !pwchKeyName[ 0 ] ) { char szKey[ 12 ]; Q_snprintf( szKey, sizeof(szKey), "%s", pszKey ); Q_strupr( szKey ); g_pVGuiLocalize->ConvertANSIToUnicode( pszKey, wszKey, sizeof( wszKey ) ); pwchKeyName = wszKey; } surface()->DrawSetTextColor( m_SquadMate_ExtraItem_hotkey_color ); surface()->DrawSetTextFont( m_hDefaultFont ); surface()->GetTextSize( m_hDefaultFont, pwchKeyName, w, t ); surface()->DrawSetTextPos( m_nExtraItem_hotkey_x + m_nMarinePortrait_x - w, m_nExtraItem_hotkey_y + m_nMarinePortrait_y ); surface()->DrawUnicodeString( pwchKeyName ); } } } } // Charges for primary/secondary items for ( int i = ASW_INVENTORY_SLOT_PRIMARY; i < ASW_INVENTORY_SLOT_EXTRA; i++ ) { if ( !m_pLocalMarine ) continue; CASW_Weapon *pWeapon = m_pLocalMarine->GetASWWeapon( i ); if ( pWeapon ) { const CASW_WeaponInfo *pInfo = pWeapon->GetWeaponInfo(); if ( !pInfo->m_bShowCharges ) continue; int x = m_nWeapon_w - YRES( 20 ); int y = m_nWeapon_t / 4; switch( i ) { case ASW_INVENTORY_SLOT_PRIMARY: { x += m_nPrimaryWeapon_x; y += m_nPrimaryWeapon_y; break; } case ASW_INVENTORY_SLOT_SECONDARY: { x += m_nSecondaryWeapon_x; y += m_nSecondaryWeapon_y; break; } } int w, t; wchar_t wszQuantity[ 12 ]; _snwprintf( wszQuantity, sizeof( wszQuantity ), L"x%d", pWeapon->Clip1() ); surface()->DrawSetTextColor( ( pWeapon == m_pLocalMarineActiveWeapon ) ? Color( 255, 255, 255, 255 ) : Color( 66, 142, 192, 255 ) ); surface()->DrawSetTextFont( m_hDefaultSmallFont ); surface()->GetTextSize( m_hDefaultSmallFont, wszQuantity, w, t ); surface()->DrawSetTextPos( x, y ); surface()->DrawUnicodeString( wszQuantity ); } } } void CASW_Hud_Master::PaintSquadMemberText( int nPosition ) { int x = m_SquadMateInfo[ nPosition ].xpos; //m_nSquadMates_x + nPosition * m_nSquadMates_spacing; int y = m_nSquadMates_y; surface()->DrawSetTextFont( m_hDefaultSmallFont ); if ( m_SquadMateInfo[ nPosition ].flHealthFraction <= 0 ) { surface()->DrawSetTextColor( m_SquadMate_name_dead_color ); } else { surface()->DrawSetTextColor( m_SquadMate_name_color ); } surface()->DrawSetTextPos( x + m_nSquadMate_name_x, y + m_nSquadMate_name_y ); surface()->DrawUnicodeString( m_SquadMateInfo[ nPosition ].wszMarineName ); if ( m_SquadMateInfo[ nPosition ].flHealthFraction <= 0 ) return; if ( m_SquadMateInfo[ nPosition ].nClips > 5 ) { static wchar_t wszBullets[ 6 ]; _snwprintf( wszBullets, sizeof( wszBullets ), L"x%d", m_SquadMateInfo[ nPosition ].nClips ); surface()->DrawSetTextPos( x + m_nSquadMate_clips_x + m_nSquadMate_clips_w, y + m_nSquadMate_clips_y ); surface()->DrawUnicodeString( wszBullets ); } if ( m_SquadMateInfo[ nPosition ].pExtraItemInfo ) { int w, t; // quantity for extra item if ( m_SquadMateInfo[ nPosition ].pExtraItemInfo->m_bShowCharges ) { surface()->DrawSetTextColor( m_SquadMate_ExtraItem_quantity_color ); wchar_t wszQuantity[ 12 ]; _snwprintf( wszQuantity, sizeof( wszQuantity ), L"x%d", m_SquadMateInfo[ nPosition ].nExtraItemQuantity ); surface()->GetTextSize( m_hDefaultSmallFont, wszQuantity, w, t ); surface()->DrawSetTextPos( x + m_nSquadMate_ExtraItem_quantity_x - w, y + m_nSquadMate_ExtraItem_quantity_y - t ); surface()->DrawUnicodeString( wszQuantity ); } if ( ASWGameResource()->IsOfflineGame() || m_SquadMateInfo[ nPosition ].pExtraItemInfo->m_bShowMultiplayerHotkey ) { // show hotkey for this marine's extra item char szBinding[ 128 ]; Q_snprintf( szBinding, sizeof( szBinding ), "asw_squad_hotbar %d", nPosition + 1 ); const char *pszKey = ASW_FindKeyBoundTo( szBinding ); char szKey[ 12 ]; Q_snprintf( szKey, sizeof(szKey), "%s", pszKey ); Q_strupr( szKey ); wchar_t wszKey[ 12 ]; g_pVGuiLocalize->ConvertANSIToUnicode( pszKey, wszKey, sizeof( wszKey ) ); surface()->DrawSetTextColor( m_SquadMate_ExtraItem_hotkey_color ); surface()->GetTextSize( m_hDefaultFont, wszKey, w, t ); surface()->DrawSetTextPos( x + m_nSquadMate_ExtraItem_hotkey_x - w, y + m_nSquadMate_ExtraItem_hotkey_y ); surface()->DrawUnicodeString( wszKey ); } } } void CASW_Hud_Master::ActivateHotbarItem( int nSlot ) { if ( nSlot < 0 || nSlot >= MAX_SQUADMATE_HUD_POSITIONS ) return; if ( !m_SquadMateInfo[ nSlot ].bPositionActive || !m_SquadMateInfo[ nSlot ].hMarine.Get() ) return; if ( !m_SquadMateInfo[ nSlot ].pExtraItemInfo || !(m_SquadMateInfo[ nSlot ].pExtraItemInfo->m_bOffhandActivate || ( m_SquadMateInfo[ nSlot ].bInhabited && m_SquadMateInfo[ nSlot ].pExtraItemInfo->m_bHUDPlayerActivate ) ) ) return; if ( m_SquadMateInfo[ nSlot ].hMarine->GetCommander() != C_ASW_Player::GetLocalASWPlayer() ) { // We don't own this guy, so let's do an appropriate emote! if ( m_SquadMateInfo[ nSlot ].pExtraItemInfo->m_iSquadEmote != -1 ) { char buffer[ 64 ]; Q_snprintf(buffer, sizeof(buffer), "cl_emote %d", m_SquadMateInfo[ nSlot ].pExtraItemInfo->m_iSquadEmote ); engine->ClientCmd( buffer ); } } else { char buffer[ 64 ]; Q_snprintf(buffer, sizeof(buffer), "cl_ai_offhand %d %d", m_SquadMateInfo[ nSlot ].nExtraItemInventoryIndex, m_SquadMateInfo[ nSlot ].hMarine->entindex() ); engine->ClientCmd( buffer ); CLocalPlayerFilter filter; C_BaseEntity::EmitSound( filter, -1 /*SOUND_FROM_LOCAL_PLAYER*/, "ASWInterface.Button3" ); } } int CASW_Hud_Master::GetHotBarSlot( const char *szWeaponName ) { for ( int i = 0; i < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { if ( m_SquadMateInfo[ i ].bPositionActive && m_SquadMateInfo[ i ].pExtraItemInfo ) { if ( V_strcmp( m_SquadMateInfo[ i ].pExtraItemInfo->szClassName, szWeaponName ) == 0 ) { return i; } } } for ( int i = 0; i < MAX_SQUADMATE_HUD_POSITIONS; i++ ) { if ( m_SquadMateInfo[ i ].bPositionActive && m_SquadMateInfo[ i ].pExtraItemInfoShift ) { if ( V_strcmp( m_SquadMateInfo[ i ].pExtraItemInfoShift->szClassName, szWeaponName ) == 0 ) { // Special value for SHIFT! return 100 + i; } } } return -1; } bool CASW_Hud_Master::OwnsHotBarSlot( C_ASW_Player *pPlayer, int nSlot ) { if ( nSlot >= 100 ) { nSlot -= 100; } C_ASW_Marine *pMarine = m_SquadMateInfo[ nSlot ].hMarine; if ( !pMarine ) return false; return ( pMarine->GetCommander() == pPlayer ); } void SquadHotbar( const CCommand &args ) { C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if (!pPlayer) return; if ( args.ArgC() < 2 ) return; CASW_Hud_Master *pHUD = GET_HUDELEMENT( CASW_Hud_Master ); if ( !pHUD ) return; pHUD->ActivateHotbarItem( atoi( args[1] ) - 1 ); } static ConCommand asw_squad_hotbar( "asw_squad_hotbar", SquadHotbar, "Activate a squad hotbar button", 0 ); void CASW_Hud_Master::StopItemFX( C_ASW_Marine *pMarine, float flDeleteTime, bool bFailed ) { if ( !pMarine ) return; // loops through to see if we already have an order effect for this marine HotbarOrderEffectsList_t::IndexLocalType_t f = m_hHotbarOrderEffects.Head(); while ( m_hHotbarOrderEffects.IsValidIndex( f ) ) { // advance before deleting the pointer out from under us const HotbarOrderEffectsList_t::IndexLocalType_t i = f; f = m_hHotbarOrderEffects.Next( f ); if ( m_hHotbarOrderEffects[i].iEffectID == pMarine->entindex() && m_hHotbarOrderEffects[i].pEffect ) { if ( bFailed ) { m_hHotbarOrderEffects[i].flRemoveAtTime = MAX( flDeleteTime, 0.5f ); m_hHotbarOrderEffects[i].pEffect->SetControlPoint( 2, Vector( 0, 1, 0 ) ); break; } if ( flDeleteTime > 0 ) { m_hHotbarOrderEffects[i].flRemoveAtTime = flDeleteTime; break; } pMarine->ParticleProp()->StopEmission( m_hHotbarOrderEffects[i].pEffect ); m_hHotbarOrderEffects[i].pEffect = NULL; m_hHotbarOrderEffects.Remove(i); break; } } } //----------------------------------------------------------------------------- // Purpose: Message handler for ASWOrderUseItemFX message //----------------------------------------------------------------------------- void CASW_Hud_Master::MsgFunc_ASWOrderUseItemFX( bf_read &msg ) { int iMarine = msg.ReadShort(); C_ASW_Marine *pMarine = dynamic_cast(ClientEntityList().GetEnt(iMarine)); // turn iMarine ent index into the marine if ( !pMarine ) return; int iOrderType = msg.ReadShort(); int iInventorySlot = msg.ReadShort(); Vector vecPosition; vecPosition.x = msg.ReadFloat(); vecPosition.y = msg.ReadFloat(); vecPosition.z = msg.ReadFloat(); // loops through to see if we already have an order effect for this marine StopItemFX( pMarine ); const char *pszClassName = NULL; switch( iOrderType ) { case ASW_USE_ORDER_WITH_ITEM: { // check we have an item in that slot CASW_Weapon* pWeapon = pMarine->GetASWWeapon( iInventorySlot ); if ( !pWeapon || !pWeapon->GetWeaponInfo() || !pWeapon->GetWeaponInfo()->m_bOffhandActivate ) return; pszClassName = pWeapon->GetClassname(); } break; case ASW_USE_ORDER_HACK: { pszClassName = "hacking_icon"; // no weapon class associated with this } break; default: { Assert( false ); // unspecified order type return; } break; } CNewParticleEffect *pEffect = pMarine->ParticleProp()->Create( "order_use_item", PATTACH_ABSORIGIN ); if ( pEffect ) { pMarine->ParticleProp()->AddControlPoint( pEffect, 1, pMarine, PATTACH_CUSTOMORIGIN ); pEffect->SetControlPoint( 1, vecPosition + Vector( 0.0f, 0.0f, 5.0f ) ); for ( int i = 0; i < NUM_USE_ITEM_ORDER_CLASSES; i++ ) { if ( pszUseItemOrderClasses[i] && !Q_strcmp ( pszUseItemOrderClasses[i] , pszClassName ) ) { pEffect->SetControlPoint( 2, Vector( i, 0, 0 ) ); break; } } HotbarOrderEffectsList_t::IndexLocalType_t iIndex = m_hHotbarOrderEffects.AddToTail(); m_hHotbarOrderEffects[iIndex].iEffectID = iMarine; m_hHotbarOrderEffects[iIndex].pEffect = pEffect; } } void CASW_Hud_Master::MsgFunc_ASWOrderStopItemFX( bf_read &msg ) { int iMarine = msg.ReadShort(); C_ASW_Marine *pMarine = dynamic_cast(ClientEntityList().GetEnt(iMarine)); // turn iMarine ent index into the marine if ( !pMarine ) return; bool bShouldDelay = msg.ReadOneBit() ? true : false; bool bFailed = msg.ReadOneBit() ? true : false; // loops through to see if we already have an order effect for this marine if ( bFailed ) StopItemFX( pMarine, gpGlobals->curtime + 2.0f, true ); else if ( bShouldDelay ) StopItemFX( pMarine, gpGlobals->curtime + 2.0f ); else StopItemFX( pMarine ); } // used by blink and assault jets when player tries to jump to a bad spot void CASW_Hud_Master::MsgFunc_ASWInvalidDesination( bf_read &msg ) { int iMarine = msg.ReadShort(); C_ASW_Marine *pMarine = dynamic_cast(ClientEntityList().GetEnt(iMarine)); // turn iMarine ent index into the marine if ( !pMarine ) return; Vector vecPosition; vecPosition.x = msg.ReadFloat(); vecPosition.y = msg.ReadFloat(); vecPosition.z = msg.ReadFloat(); CNewParticleEffect *pEffect = pMarine->ParticleProp()->Create( "invalid_destination", PATTACH_ABSORIGIN ); if ( pEffect ) { pMarine->ParticleProp()->AddControlPoint( pEffect, 1, pMarine, PATTACH_CUSTOMORIGIN ); pEffect->SetControlPoint( 1, vecPosition ); } pMarine->EmitSound( "ASW_Weapon.InvalidDestination" ); } extern int g_asw_iPlayerListOpen; bool CASW_Hud_Master::ShouldDraw() { if ( g_asw_iPlayerListOpen > 0 ) return false; return CASW_HudElement::ShouldDraw(); } const HudSheetTexture_t* CASW_Hud_Master::GetDeadIconUVs() { return &m_Sheet1[ UV_DeadIcon ]; } int CASW_Hud_Master::GetDeadIconTextureID() { return m_nSheet1ID; }