mirror of
https://github.com/nillerusr/source-engine.git
synced 2025-09-03 09:42:32 +00:00
1559 lines
48 KiB
C++
1559 lines
48 KiB
C++
#include "cbase.h"
|
|
#include "asw_hud_3dmarinenames.h"
|
|
#include "hud_macros.h"
|
|
#include "view.h"
|
|
|
|
#include "iclientmode.h"
|
|
|
|
#define PAIN_NAME "sprites/%d_pain.vmt"
|
|
|
|
#include <KeyValues.h>
|
|
#include <vgui/ISurface.h>
|
|
#include <vgui/ISystem.h>
|
|
#include <vgui_controls/AnimationController.h>
|
|
|
|
#include <vgui/ILocalize.h>
|
|
|
|
#include <filesystem.h>
|
|
#include <keyvalues.h>
|
|
|
|
#include "asw_hudelement.h"
|
|
#include "hud_numericdisplay.h"
|
|
|
|
#include "c_asw_door.h"
|
|
#include "c_asw_game_resource.h"
|
|
#include "c_asw_player.h"
|
|
#include "c_asw_marine.h"
|
|
#include "asw_marine_profile.h"
|
|
#include "c_asw_marine_resource.h"
|
|
#include "c_asw_use_area.h"
|
|
#include "asw_weapon_medical_satchel_shared.h"
|
|
#include "ConVar.h"
|
|
#include "tier0/vprof.h"
|
|
#include "idebugoverlaypanel.h"
|
|
#include "engine/IVDebugOverlay.h"
|
|
#include "vguimatsurface/imatsystemsurface.h"
|
|
#include "iasw_client_vehicle.h"
|
|
#include "c_playerresource.h"
|
|
#include "datacache/imdlcache.h"
|
|
#include "asw_util_shared.h"
|
|
#include "asw_hud_objective.h"
|
|
#include "voice_status.h"
|
|
#include "cdll_bounded_cvars.h"
|
|
#include "asw_input.h"
|
|
|
|
// 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;
|
|
extern ConVar asw_DebugAutoAim;
|
|
extern ConVar asw_fast_reload_enabled;
|
|
|
|
ConVar asw_voice_side_icon("asw_voice_side_icon", "0", FCVAR_CHEAT, "Set to 1 to use the voice indicators on the side of the screen instead of the ones next to the 3d player names");
|
|
ConVar asw_marine_names("asw_marine_names", "1", FCVAR_NONE, "Whether to show the marine name");
|
|
ConVar asw_player_names("asw_player_names", "1", FCVAR_NONE, "Whether to show player names under marines or not. Set to 2 to show both player and marine name.");
|
|
ConVar asw_marine_edge_names("asw_marine_edge_names", "1", FCVAR_NONE, "Prevent marine names from going off the edge of the screen");
|
|
ConVar asw_world_healthbars("asw_world_healthbars", "1", FCVAR_NONE, "Shows health bars in the game world");
|
|
ConVar asw_world_usingbars("asw_world_usingbars", "1", FCVAR_NONE, "Shows using bars in the game world");
|
|
ConVar asw_marine_labels_cursor_maxdist( "asw_marine_labels_cursor_maxdist", "70", FCVAR_NONE, "Only marines within this distance of the cursor will get their health bar drawn" );
|
|
ConVar asw_fast_reload_under_marine( "asw_fast_reload_under_marine", "0", FCVAR_NONE, "Draw the active reload bar under the marine?" );
|
|
ConVar asw_world_healthbar_class_icon( "asw_world_healthbar_class_icon", "0", FCVAR_NONE, "Show class icon on mouse over" );
|
|
|
|
#define ASW_MAX_MARINE_NAMES 8
|
|
#define ASW_MIN_MARINE_ARROW_SIZE 20
|
|
#define ASW_MAX_MARINE_ARROW_SIZE 60
|
|
#define ASW_MAX_MARINE_OFFSCREEN_START_DISTANCE 600.0f
|
|
#define ASW_MAX_MARINE_OFFSCREEN_END_DISTANCE 1800.0f
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Shows the marines names drawn on top of the 3D view
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CASWHud3DMarineNames::CASWHud3DMarineNames( const char *pElementName ) : vgui::Panel( GetClientMode()->GetViewport(), "ASWHud3DMarineNames" ), CASW_HudElement( "ASWHud3DMarineNames" )
|
|
{
|
|
SetHiddenBits( HIDEHUD_REMOTE_TURRET );
|
|
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
|
SetScheme(scheme);
|
|
|
|
for( int i = 0; i < ASW_MAX_PLAYERS; i++ )
|
|
{
|
|
m_flLastTalkingTime[i] = 0;
|
|
}
|
|
m_3DSpeakingList.ClearAll();
|
|
}
|
|
|
|
CASWHud3DMarineNames::~CASWHud3DMarineNames()
|
|
{
|
|
|
|
}
|
|
|
|
DECLARE_HUDELEMENT( CASWHud3DMarineNames );
|
|
|
|
void CASWHud3DMarineNames::Init()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
void CASWHud3DMarineNames::Reset()
|
|
{
|
|
SetPaintBackgroundEnabled(false);
|
|
|
|
m_hHealthQueuedMarine = NULL;
|
|
m_hHealthMarine = NULL;
|
|
m_bHealthQueuedMarine = false;
|
|
m_fHealthAlpha = 0;
|
|
|
|
for( int i = 0; i < ASW_MAX_PLAYERS; i++ )
|
|
{
|
|
m_flLastTalkingTime[i] = 0;
|
|
}
|
|
m_3DSpeakingList.ClearAll();
|
|
|
|
m_flLastReloadProgress = 0;
|
|
m_flLastNextAttack = 0;
|
|
m_flLastFastReloadStart = 0;
|
|
m_flLastFastReloadEnd = 0;
|
|
}
|
|
|
|
void CASWHud3DMarineNames::VidInit()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
void CASWHud3DMarineNames::ApplySchemeSettings(IScheme *pScheme)
|
|
{
|
|
BaseClass::ApplySchemeSettings(pScheme);
|
|
SetBgColor(Color(0,0,0,0));
|
|
//m_hMarineNameFont = ASW_GetDefaultFont(false);
|
|
}
|
|
|
|
bool CASWHud3DMarineNames::ShouldDraw( void )
|
|
{
|
|
// Undone! -Jeep
|
|
//CASWHudObjective *pObjectives = GET_HUDELEMENT( CASWHudObjective );
|
|
|
|
//if ( pObjectives && pObjectives->GetBgColor().a() != 0 )
|
|
//{
|
|
// // Don't draw this stuff while we're showing objectives in the center!
|
|
// return false;
|
|
//}
|
|
|
|
return asw_draw_hud.GetBool() && CASW_HudElement::ShouldDraw();
|
|
}
|
|
void CASWHud3DMarineNames::OnThink()
|
|
{
|
|
BaseClass::OnThink();
|
|
UpdateHealthTooltip();
|
|
}
|
|
|
|
void CASWHud3DMarineNames::Paint()
|
|
{
|
|
VPROF_BUDGET( "CASWHud3DMarineNames::Paint", VPROF_BUDGETGROUP_ASW_CLIENT );
|
|
|
|
BaseClass::Paint();
|
|
//PaintFontTest();
|
|
MDLCACHE_CRITICAL_SECTION();
|
|
PaintMarineNameLabels();
|
|
PaintBoxesAroundUseEntities();
|
|
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
|
if (pPlayer)
|
|
{
|
|
/*
|
|
// check for drawing autoaim crosshair
|
|
if (pPlayer->m_ASWLocal.m_hAutoAimTarget.Get() && pPlayer->GetMarine())
|
|
{
|
|
C_ASW_Marine *pMarine = pPlayer->GetMarine();
|
|
C_ASW_Marine_Resource *pMR = pMarine->GetMarineResource();
|
|
if (pMR && pMR->IsFiring())
|
|
{
|
|
C_ASW_Weapon *pWeapon = pMarine->GetActiveASWWeapon();
|
|
if (pWeapon->IsOffensiveWeapon())
|
|
PaintAutoaimCrosshairOn(pPlayer->m_ASWLocal.m_hAutoAimTarget.Get());
|
|
}
|
|
}
|
|
*/
|
|
if (pPlayer->GetHighlightEntity())
|
|
{
|
|
PaintBoxAround(pPlayer->GetHighlightEntity(), 6);
|
|
}
|
|
}
|
|
|
|
if ( ASWInput() && ASWInput()->GetAutoaimEntity() )
|
|
{
|
|
PaintAutoaimCrosshairOn( ASWInput()->GetAutoaimEntity() );
|
|
}
|
|
|
|
PaintTrackedHealth();
|
|
if ( asw_DebugAutoAim.GetBool() )
|
|
{
|
|
PaintAimingDebug();
|
|
}
|
|
|
|
}
|
|
|
|
/// simple convenience for printing unformatted text with a drop shadow
|
|
void CASW_HudElement::DrawColoredTextWithDropShadow( const vgui::HFont &font, int x, int y, int r, int g, int b, int a, char *fmt )
|
|
{
|
|
g_pMatSystemSurface->DrawColoredText( font, x+1, y+1, 0, 0, 0, a, fmt );
|
|
g_pMatSystemSurface->DrawColoredText( font, x+0, y+0, r, g, b, a, fmt );
|
|
}
|
|
|
|
void CASWHud3DMarineNames::PaintAutoaimCrosshairOn(C_BaseEntity *pEnt)
|
|
{
|
|
if (!pEnt)
|
|
return;
|
|
|
|
Vector pos = (pEnt->WorldSpaceCenter() - pEnt->GetAbsOrigin()) + pEnt->GetRenderOrigin();
|
|
Vector screenPos;
|
|
debugoverlay->ScreenPosition( pos, screenPos );
|
|
|
|
surface()->DrawSetColor(Color(255,255,255,255));
|
|
surface()->DrawSetTexture(m_nAutoaimCrosshairTexture);
|
|
|
|
int xhair_size = 26.0f * (ScreenHeight() / 768.0f);
|
|
|
|
Vertex_t points[4] =
|
|
{
|
|
Vertex_t( Vector2D(screenPos.x - xhair_size, screenPos.y - xhair_size), Vector2D(0,0) ),
|
|
Vertex_t( Vector2D(screenPos.x + xhair_size, screenPos.y - xhair_size), Vector2D(1,0) ),
|
|
Vertex_t( Vector2D(screenPos.x + xhair_size, screenPos.y + xhair_size), Vector2D(1,1) ),
|
|
Vertex_t( Vector2D(screenPos.x - xhair_size, screenPos.y + xhair_size), Vector2D(0,1) )
|
|
};
|
|
surface()->DrawTexturedPolygon( 4, points );
|
|
}
|
|
|
|
void CASWHud3DMarineNames::PaintBoxAround(C_BaseEntity* pEnt, int padding)
|
|
{
|
|
// find the volume this entity takes up
|
|
Vector mins, maxs;
|
|
//mins = pEnt->WorldAlignMins() + pEnt->GetAbsOrigin();
|
|
//maxs = pEnt->WorldAlignMaxs() + pEnt->GetAbsOrigin();
|
|
pEnt->GetRenderBoundsWorldspace(mins,maxs);
|
|
|
|
|
|
// pull out all 8 corners of this volume
|
|
Vector worldPos[8];
|
|
Vector screenPos[8];
|
|
worldPos[0] = mins;
|
|
worldPos[1] = mins; worldPos[1].x = maxs.x;
|
|
worldPos[2] = mins; worldPos[2].y = maxs.y;
|
|
worldPos[3] = mins; worldPos[3].z = maxs.z;
|
|
worldPos[4] = mins;
|
|
worldPos[5] = maxs; worldPos[5].x = mins.x;
|
|
worldPos[6] = maxs; worldPos[6].y = mins.y;
|
|
worldPos[7] = maxs; worldPos[7].z = mins.z;
|
|
|
|
// convert them to screen space
|
|
for (int k=0;k<8;k++)
|
|
{
|
|
debugoverlay->ScreenPosition( worldPos[k], screenPos[k] );
|
|
}
|
|
|
|
// find the rectangle bounding all screen space points
|
|
Vector topLeft = screenPos[0];
|
|
Vector bottomRight = screenPos[0];
|
|
for (int k=0;k<8;k++)
|
|
{
|
|
topLeft.x = MIN(screenPos[k].x, topLeft.x);
|
|
topLeft.y = MIN(screenPos[k].y, topLeft.y);
|
|
bottomRight.x = MAX(screenPos[k].x, bottomRight.x);
|
|
bottomRight.y = MAX(screenPos[k].y, bottomRight.y);
|
|
}
|
|
int BracketSize = padding; // todo: set by screen res?
|
|
|
|
// pad it a bit
|
|
topLeft.x -= BracketSize * 2;
|
|
topLeft.y -= BracketSize * 2;
|
|
bottomRight.x += BracketSize * 2;
|
|
bottomRight.y += BracketSize * 2;
|
|
|
|
// draw it
|
|
vgui::surface()->DrawSetColor(Color(255,255,255,192));
|
|
|
|
vgui::surface()->DrawLine(topLeft.x, topLeft.y, topLeft.x + BracketSize, topLeft.y);
|
|
vgui::surface()->DrawLine(topLeft.x, topLeft.y, topLeft.x, topLeft.y + BracketSize);
|
|
vgui::surface()->DrawLine(topLeft.x, bottomRight.y, topLeft.x + BracketSize, bottomRight.y);
|
|
vgui::surface()->DrawLine(topLeft.x, bottomRight.y, topLeft.x, bottomRight.y - BracketSize);
|
|
vgui::surface()->DrawLine(bottomRight.x, topLeft.y, bottomRight.x - BracketSize, topLeft.y);
|
|
vgui::surface()->DrawLine(bottomRight.x, topLeft.y, bottomRight.x, topLeft.y + BracketSize);
|
|
vgui::surface()->DrawLine(bottomRight.x, bottomRight.y, bottomRight.x, bottomRight.y - BracketSize);
|
|
vgui::surface()->DrawLine(bottomRight.x, bottomRight.y, bottomRight.x - BracketSize, bottomRight.y);
|
|
}
|
|
|
|
void CASWHud3DMarineNames::PaintBoxesAroundUseEntities()
|
|
{
|
|
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
|
if ( !pPlayer || !pPlayer->GetMarine() || pPlayer->GetMarine()->GetHealth() <= 0 )
|
|
return;
|
|
|
|
C_BaseEntity *pEnt = NULL;
|
|
|
|
if ( pPlayer->GetNumUseEntities() > 0 )
|
|
{
|
|
pEnt = pPlayer->GetUseEntity();
|
|
if ( !pEnt )
|
|
{
|
|
pEnt = pPlayer->GetUseEntity( 0 );
|
|
}
|
|
|
|
IASW_Client_Usable_Entity* pUsable = dynamic_cast< IASW_Client_Usable_Entity* >( pEnt );
|
|
if ( !pUsable || !pUsable->ShouldPaintBoxAround() )
|
|
{
|
|
pEnt = NULL;
|
|
}
|
|
}
|
|
|
|
if ( pEnt )
|
|
{
|
|
C_ASW_Use_Area *pArea = dynamic_cast< C_ASW_Use_Area* >( pEnt );
|
|
if ( pArea )
|
|
{
|
|
if ( pArea->GetGlowEntity() )
|
|
{
|
|
ASWInput()->SetUseGlowEntity( pArea->GetGlowEntity() );
|
|
}
|
|
else
|
|
{
|
|
PaintBoxAround( pEnt, 6 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASWInput()->SetUseGlowEntity( pEnt );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASWInput()->SetUseGlowEntity( NULL );
|
|
}
|
|
}
|
|
|
|
void CASWHud3DMarineNames::PaintMarineNameLabels()
|
|
{
|
|
C_ASW_Player *local = C_ASW_Player::GetLocalASWPlayer();
|
|
if ( !local )
|
|
return;
|
|
|
|
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
|
if ( !pGameResource )
|
|
return;
|
|
|
|
int count = 0;
|
|
int my_count = 0;
|
|
for ( int i = 0; i < pGameResource->GetMaxMarineResources(); i++ )
|
|
{
|
|
C_ASW_Marine_Resource *pMR = pGameResource->GetMarineResource( i );
|
|
if ( pMR && pMR->GetHealthPercent() > 0 )
|
|
{
|
|
C_ASW_Marine *pMarine = pMR->GetMarineEntity();
|
|
if ( pMarine )
|
|
{
|
|
if ( pMarine->GetCommander() == local )
|
|
{
|
|
PaintMarineLabel( my_count, pMarine, pMR, local->GetMarine() == pMarine );
|
|
my_count++;
|
|
}
|
|
else
|
|
{
|
|
PaintMarineLabel( -1, pMarine, pMR, false );
|
|
}
|
|
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// function: round UP to the specified power of 2
|
|
template < unsigned int N >
|
|
int RoundUpToPowerOfTwo( int x )
|
|
{
|
|
const int mask = ( 1 << N ) - 1; // known at compile time
|
|
// branchless
|
|
return ( ( x - 1 ) & ( ~mask ) ) + ( 1 << N );
|
|
|
|
// branchy:
|
|
/*
|
|
return ( x & mask ) != 0 ?
|
|
( x & ~mask ) + ( 1 << N ) :
|
|
x;
|
|
*/
|
|
}
|
|
|
|
/// for the case where the marine's label is outside
|
|
/// the bounds of the screen, compute clipping coordinates in a way
|
|
/// that properly preserves directionality
|
|
static Vector ComputeClippedMarineLabelCoordinates( float xPos, float yPos,
|
|
int screenMinX, int screenMaxX,
|
|
int screenMinY, int screenMaxY )
|
|
{
|
|
int x_edge = 0;
|
|
int y_edge = 0;
|
|
|
|
int screenWidth = screenMaxX - screenMinX;
|
|
int screenHeight = screenMaxY - screenMinY;
|
|
int screenhalfx = ( screenWidth / 2 );
|
|
int screenhalfy = ( screenHeight / 2 );
|
|
// the name is off the edge, calculate a better position to draw at than clipped (which changes direction)
|
|
int diffx = xPos - screenhalfx; // grab the direction of the marine
|
|
int diffy = yPos - screenhalfy;
|
|
|
|
// find intersection point with the right edge of the screen
|
|
bool bFound = false;
|
|
if (diffx != 0)
|
|
{
|
|
float yxratio = float(diffy) / float(diffx);
|
|
int right_x = screenhalfx;
|
|
int right_y = yxratio * right_x;
|
|
|
|
if (right_y >= -screenhalfy && right_y <= screenhalfy)
|
|
{
|
|
// we've found a valid side edge to use
|
|
if (diffx > 0)
|
|
{
|
|
xPos = screenhalfx + right_x;
|
|
yPos = screenhalfy + right_y;
|
|
x_edge = 1;
|
|
}
|
|
else
|
|
{
|
|
xPos = screenhalfx - right_x;
|
|
yPos = screenhalfy - right_y;
|
|
x_edge = 1;
|
|
}
|
|
bFound = true;
|
|
}
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
// find the intersection point with the top edge
|
|
if (diffy != 0)
|
|
{
|
|
float xyratio = float(diffx) / float(diffy);
|
|
int top_y = screenhalfy;
|
|
int top_x = xyratio * top_y;
|
|
|
|
if (top_x >= -screenhalfx && top_x <= screenhalfx)
|
|
{
|
|
// we've found a valid top/bottom edge to use
|
|
if (diffy > 0)
|
|
{
|
|
xPos = screenhalfx + top_x;
|
|
yPos = screenhalfy + top_y;
|
|
y_edge = 1;
|
|
}
|
|
else
|
|
{
|
|
xPos = screenhalfx - top_x;
|
|
yPos = screenhalfy - top_y;
|
|
y_edge = -1;
|
|
}
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
return Vector( xPos, yPos, 0 );
|
|
}
|
|
|
|
|
|
void CASWHud3DMarineNames::PaintMarineLabel( int iMyMarineNum, C_ASW_Marine * RESTRICT pMarine, C_ASW_Marine_Resource * RESTRICT pMR, bool bLocal )
|
|
{
|
|
VPROF( "CASWHud3DMarineNames::PaintMarineLabel" );
|
|
|
|
if ( !pMarine )
|
|
return;
|
|
|
|
C_ASW_Player *pLocal = C_ASW_Player::GetLocalASWPlayer();
|
|
if ( !pLocal )
|
|
return;
|
|
|
|
// Verify we have input.
|
|
Assert( ASWInput() != NULL );
|
|
|
|
wchar_t wszMarineName[ ASW_MAX_PLAYER_NAME_LENGTH_3D ];
|
|
pMR->GetDisplayName( wszMarineName, sizeof( wszMarineName ) );
|
|
|
|
/*
|
|
// make sure name is not too long
|
|
wchar_t wszMarineName[ASW_MAX_PLAYER_NAME_LENGTH_3D];
|
|
Q_wcsncpy( wszMarineName, wszMarineNameLong, sizeof( wszMarineName ) );
|
|
*/
|
|
|
|
CASW_Marine_Profile *pProfile = pMarine->GetMarineProfile();
|
|
if ( !pProfile )
|
|
return;
|
|
|
|
const wchar_t *pwszMarineProfileName = NULL;
|
|
|
|
if ( asw_player_names.GetInt() == 2 && pMarine->IsInhabited() && gpGlobals->maxClients > 1 )
|
|
{
|
|
pwszMarineProfileName = g_pVGuiLocalize->Find( pProfile->GetShortName() );
|
|
}
|
|
|
|
if ( pMarine->entindex() == ASWInput()->ASW_GetOrderingMarine() )
|
|
{
|
|
PaintBoxAround( pMarine, 6 );
|
|
}
|
|
|
|
// find the color to use
|
|
Color nMarineTextColor(255,255,255,255);
|
|
if ( bLocal ) // yellow if currently selected marine
|
|
{
|
|
nMarineTextColor[2] = 0;
|
|
}
|
|
else if ( pMR->IsInhabited() ) // other player's inhabited marines go blue
|
|
{
|
|
nMarineTextColor.SetColor( 0, 144, 188, 255 );
|
|
}
|
|
|
|
// if marine is injured pulse it red
|
|
float diffr = ( 255.0f - nMarineTextColor.r() ) * pMarine->m_fRedNamePulse;
|
|
float diffg = ( 0.0f - nMarineTextColor.g() ) * pMarine->m_fRedNamePulse;
|
|
float diffb = ( 0.0f - nMarineTextColor.b() ) * pMarine->m_fRedNamePulse;
|
|
nMarineTextColor[0] += diffr;
|
|
nMarineTextColor[1] += diffg;
|
|
nMarineTextColor[2] += diffb;
|
|
|
|
// find the position of this marine
|
|
Vector screenPos;
|
|
Vector vMarinePos = pMarine->GetRenderOrigin();
|
|
//bool bMarineIsKnockedOut = pMarine->m_hKnockedOutRagdoll.Get() || pMarine->IsIncap() ;
|
|
bool bMarineIsKnockedOut = false;
|
|
if ( pMarine->IsInVehicle() && pMarine->GetASWVehicle() && pMarine->GetASWVehicle()->GetEntity() )
|
|
{
|
|
vMarinePos = pMarine->GetASWVehicle()->GetEntity()->GetAbsOrigin();
|
|
if ( gpGlobals->maxClients>1 && pMarine->GetClientsideVehicle() && pMarine->GetClientsideVehicle()->GetEntity() )
|
|
{
|
|
vMarinePos = pMarine->GetClientsideVehicle()->GetEntity()->GetAbsOrigin();
|
|
}
|
|
}
|
|
//if ( bMarineIsKnockedOut )
|
|
//{
|
|
// CBaseEntity *pRagdoll = pMarine->m_hKnockedOutRagdoll.Get();
|
|
// MarinePos = pRagdoll ? pRagdoll->GetAbsOrigin() : pMarine->GetAbsOrigin() ;
|
|
//}
|
|
|
|
Vector vecCameraFocus;
|
|
QAngle ang;
|
|
int omx, omy;
|
|
ASWInput()->ASW_GetCameraLocation( pLocal, vecCameraFocus, ang, omx, omy, false);
|
|
|
|
float flMarineDistanceFromCamera = vecCameraFocus.DistTo( vMarinePos );
|
|
|
|
// if marine is behind the player, convert it to a shortened vector, so it doesn't go behind the plane of the camera
|
|
if ( !!debugoverlay->ScreenPosition( vMarinePos - Vector( 0.0f, 10.0f, 0.0f ), screenPos ) )
|
|
{
|
|
Vector offset;
|
|
AngleVectors( ang, &offset );
|
|
if ( ::input->CAM_IsThirdPerson() )
|
|
{
|
|
offset *= ASWInput()->ASW_GetCameraDist();
|
|
}
|
|
|
|
vecCameraFocus += offset;
|
|
Vector dir = vMarinePos - vecCameraFocus;
|
|
VectorNormalize( dir );
|
|
vMarinePos = vecCameraFocus + dir * 500;
|
|
}
|
|
|
|
if ( !debugoverlay->ScreenPosition( vMarinePos - Vector(0,10,0), screenPos ) )
|
|
{
|
|
const int nMaxX = ScreenWidth() - YRES( 50 );
|
|
const int nMaxY = ScreenHeight() - YRES( 75 );
|
|
const int nMinX = 0 + YRES( 50 );
|
|
const int nMinY = 0 + YRES( 25 );
|
|
// we're going to draw a box. The box contains some combination of these elements:
|
|
/*
|
|
+-----+
|
|
| _ |
|
|
||\ |
|
|
| \ |
|
|
| \ |
|
|
+-----+
|
|
+-------------+
|
|
| MARINE NAME |
|
|
+-------------+
|
|
[ health bar ]
|
|
[ use bar ]
|
|
+-------------+
|
|
*/
|
|
// the presence or absence and size of these elements depends on a variety of factors.
|
|
// first, is the marine on screen?
|
|
bool bMarineOnScreen = ( screenPos.x >= 0 ) && ( screenPos.x <= nMaxX ) &&
|
|
( screenPos.y >= 0 ) && ( screenPos.y <= nMaxY ) ;
|
|
|
|
// COPYPASTA: if the marine isn't on screen, compute an appropriate screen point to use
|
|
// (don't just clip to screen coords, which makes direction change inappropriately)
|
|
if ( !bMarineOnScreen )
|
|
{
|
|
screenPos = ComputeClippedMarineLabelCoordinates( screenPos.x, screenPos.y,
|
|
nMinX, nMaxX, nMinY, nMaxY );
|
|
}
|
|
|
|
// compute the size of the arrow. it draws only if a marine is off the screen.
|
|
// if the marine is alive, it's 2/57.6 the height of the screen. Otherwise, it is
|
|
// 6/57.6. It is encapsulated in a square.
|
|
int iArrowSize = 0;
|
|
|
|
if ( !bMarineOnScreen )
|
|
{
|
|
int iArrowScale = ASW_MAX_MARINE_ARROW_SIZE;
|
|
|
|
if ( !bMarineIsKnockedOut )
|
|
{
|
|
float flInterpArrowScale = 0.0f;
|
|
|
|
if ( flMarineDistanceFromCamera > ASW_MAX_MARINE_OFFSCREEN_END_DISTANCE )
|
|
{
|
|
flInterpArrowScale = 1.0f;
|
|
}
|
|
else if ( flMarineDistanceFromCamera > ASW_MAX_MARINE_OFFSCREEN_START_DISTANCE )
|
|
{
|
|
flInterpArrowScale = ( flMarineDistanceFromCamera - ASW_MAX_MARINE_OFFSCREEN_START_DISTANCE ) / ( ASW_MAX_MARINE_OFFSCREEN_END_DISTANCE - ASW_MAX_MARINE_OFFSCREEN_START_DISTANCE );
|
|
}
|
|
|
|
iArrowScale = ASW_MIN_MARINE_ARROW_SIZE + flInterpArrowScale * ( ASW_MAX_MARINE_ARROW_SIZE - ASW_MIN_MARINE_ARROW_SIZE );
|
|
}
|
|
|
|
iArrowSize = iArrowScale * nMaxY / 576;
|
|
iArrowSize = RoundUpToPowerOfTwo<1>(iArrowSize);
|
|
}
|
|
|
|
// compute the size of the health bar.
|
|
int nHealthBarWidth = 0;
|
|
int nHealthBarHeight = 0;
|
|
|
|
if ( asw_world_healthbars.GetBool() && bMarineOnScreen ) // || !bMarineOnScreen
|
|
{
|
|
// only draw health bars for marines near the cursor or their health is low/healing
|
|
int idx = ASWGameResource()->GetMarineCrosshairCache()->FindIndexForMarine( pMarine );
|
|
if ( //!bMarineOnScreen ||
|
|
( idx >= 0 && ASWGameResource()->GetMarineCrosshairCache()->GetElement(idx).m_fDistToCursor < asw_marine_labels_cursor_maxdist.GetFloat() ) ||
|
|
pMR->GetHealthPercent() < 0.4f || pMR->IsInfested() || pMarine->m_fLastHealTime + 1.0f > gpGlobals->curtime )
|
|
{
|
|
nHealthBarWidth = GetHealthBarMaxWidth( bMarineIsKnockedOut );
|
|
nHealthBarHeight = MAX( GetClassIconSize( bMarineOnScreen ), GetHealthBarMaxHeight( bMarineIsKnockedOut ) );
|
|
}
|
|
}
|
|
|
|
// compute the size of the using bar.
|
|
int nUsingBarWidth = 0;
|
|
int nUsingBarHeight = 0;
|
|
if ( asw_world_usingbars.GetBool() && bMarineOnScreen && !bLocal && GetUsingFraction( pMarine ) > 0 )
|
|
{
|
|
nUsingBarWidth = GetUsingBarMaxWidth();
|
|
nUsingBarHeight = GetUsingBarMaxHeight();
|
|
}
|
|
|
|
// compute the height and width of the marine's name.
|
|
const vgui::HFont nMarineFont = bMarineOnScreen ? m_hMarineNameFont : m_hSmallMarineNameFont;
|
|
|
|
int nMarineNameWidth = 0, nMarineNameHeight = 0;
|
|
int nMarineProfileNameWidth = 0, nMarineProfileNameHeight = 0;
|
|
if ( asw_marine_names.GetBool() )
|
|
{
|
|
g_pMatSystemSurface->GetTextSize( nMarineFont, wszMarineName, nMarineNameWidth, nMarineNameHeight );
|
|
}
|
|
if ( pwszMarineProfileName && bMarineOnScreen )
|
|
{
|
|
g_pMatSystemSurface->GetTextSize( m_hSmallMarineNameFont, pwszMarineProfileName, nMarineProfileNameWidth, nMarineProfileNameHeight );
|
|
}
|
|
|
|
// this is the vertical padding between the arrow and the marine name, or the marine name and the player name
|
|
int nLineSpacing = nMarineNameHeight >> 3;
|
|
|
|
// compute the total height of the label box
|
|
#define PAD(x) ((x) + isel((x), nLineSpacing, 0))
|
|
int nTotalBoxHeight = PAD( iArrowSize ) +
|
|
PAD( nHealthBarHeight ) +
|
|
PAD( nUsingBarHeight ) +
|
|
nMarineNameHeight +
|
|
nMarineProfileNameHeight;
|
|
int nTotalBoxWidth = MAX( nMarineNameWidth, MAX( iArrowSize, nHealthBarWidth ) );
|
|
nTotalBoxWidth = MAX( nMarineProfileNameWidth, nTotalBoxWidth );
|
|
#undef PAD
|
|
|
|
// round the figures *UP* to the nearest multiple of 2
|
|
nTotalBoxHeight = RoundUpToPowerOfTwo<1>(nTotalBoxHeight); // ( nTotalBoxHeight & 1 ) ? nTotalBoxHeight + 1 : nTotalBoxHeight;
|
|
nTotalBoxWidth = RoundUpToPowerOfTwo<1>(nTotalBoxWidth); // ( nTotalBoxWidth & 1 ) ? nTotalBoxWidth + 1 : nTotalBoxWidth ;
|
|
Assert( nTotalBoxHeight < nMaxY );
|
|
Assert( nTotalBoxWidth < nMaxX );
|
|
|
|
// now, determine where to draw the box. we would like it to be centered on the marine,
|
|
// but if necessary we'll push it in from the sides
|
|
int nBoxCenterX = screenPos.x;
|
|
int nBoxCenterY = screenPos.y + nTotalBoxHeight/2;
|
|
|
|
// if off to the left, push to the right
|
|
if ( nBoxCenterX - ( nTotalBoxWidth / 2 ) < nMinX )
|
|
{
|
|
nBoxCenterX -= nBoxCenterX - ( nTotalBoxWidth / 2 ) - nMinX;
|
|
}
|
|
else if ( nBoxCenterX + ( nTotalBoxWidth / 2 ) >= nMaxX )
|
|
// if off to the right, push to the left
|
|
{
|
|
nBoxCenterX -= nBoxCenterX + ( nTotalBoxWidth / 2 ) - nMaxX;
|
|
}
|
|
|
|
// if too high, push down
|
|
if ( nBoxCenterY - ( nTotalBoxHeight / 2 ) < nMinY )
|
|
{
|
|
nBoxCenterY -= nBoxCenterY - ( nTotalBoxHeight / 2 ) - nMinY;
|
|
}
|
|
else if ( nBoxCenterY + ( nTotalBoxHeight / 2 ) > nMaxY )
|
|
{ // if too high, push up
|
|
nBoxCenterY -= nBoxCenterY + ( nTotalBoxHeight / 2 ) - nMaxY;
|
|
}
|
|
|
|
// compute the top left, top right, bot left, and bot right coords for convenience
|
|
// int nBoxLeftExtent = nBoxCenterX - ( nTotalBoxWidth / 2 );
|
|
// int nBoxRightExtent = nBoxCenterX + ( nTotalBoxWidth / 2 );
|
|
int nBoxTopExtent = nBoxCenterY - ( nTotalBoxHeight / 2 );
|
|
// int nBoxBotExtent = nBoxCenterY + ( nTotalBoxHeight / 2 );
|
|
|
|
///////////////////////////////
|
|
// now draw from top to bottom
|
|
///////////////////////////////
|
|
int nCursorY = nBoxTopExtent;
|
|
if ( iArrowSize > 0 )
|
|
{
|
|
int iArrowHalfSize = iArrowSize / 2;
|
|
// draw a red pointing, potentially blinking, arrow
|
|
Vector vecFacing(screenPos.x - (ScreenWidth() * 0.5f), screenPos.y - (ScreenHeight() * 0.5f), 0);
|
|
float fFacingYaw = -UTIL_VecToYaw(vecFacing);
|
|
Vector2D vArrowCenter( nBoxCenterX , nCursorY + iArrowHalfSize );
|
|
|
|
Vector vecCornerTL(-iArrowHalfSize, -iArrowHalfSize, 0);
|
|
Vector vecCornerTR(iArrowHalfSize, -iArrowHalfSize, 0);
|
|
Vector vecCornerBR(iArrowHalfSize, iArrowHalfSize, 0);
|
|
Vector vecCornerBL(-iArrowHalfSize, iArrowHalfSize, 0);
|
|
Vector vecCornerTL_rotated, vecCornerTR_rotated, vecCornerBL_rotated, vecCornerBR_rotated;
|
|
|
|
// rotate it by our facing yaw
|
|
QAngle angFacing(0, -fFacingYaw, 0);
|
|
VectorRotate(vecCornerTL, angFacing, vecCornerTL_rotated);
|
|
VectorRotate(vecCornerTR, angFacing, vecCornerTR_rotated);
|
|
VectorRotate(vecCornerBR, angFacing, vecCornerBR_rotated);
|
|
VectorRotate(vecCornerBL, angFacing, vecCornerBL_rotated);
|
|
|
|
// if the pointee marine is KO'd, make the arrow blink.
|
|
if ( bMarineIsKnockedOut )
|
|
{
|
|
surface()->DrawSetColor( fmod( gpGlobals->curtime , 0.5f ) <= 0.25f ? Color(255,0,0,255) : Color(0,0,0,0) );
|
|
}
|
|
else
|
|
{
|
|
surface()->DrawSetColor( Color(131,151,160,255) );
|
|
}
|
|
|
|
surface()->DrawSetTexture(m_nMarinePointerTexture);
|
|
|
|
Vertex_t points[4] =
|
|
{
|
|
Vertex_t( Vector2D(vArrowCenter.x + vecCornerTL_rotated.x, vArrowCenter.y + vecCornerTL_rotated.y),
|
|
Vector2D(0,0) ),
|
|
Vertex_t( Vector2D(vArrowCenter.x + vecCornerTR_rotated.x, vArrowCenter.y + vecCornerTR_rotated.y),
|
|
Vector2D(1,0) ),
|
|
Vertex_t( Vector2D(vArrowCenter.x + vecCornerBR_rotated.x, vArrowCenter.y + vecCornerBR_rotated.y),
|
|
Vector2D(1,1) ),
|
|
Vertex_t( Vector2D(vArrowCenter.x + vecCornerBL_rotated.x, vArrowCenter.y + vecCornerBL_rotated.y),
|
|
Vector2D(0,1) )
|
|
};
|
|
surface()->DrawTexturedPolygon( 4, points );
|
|
|
|
nCursorY += iArrowSize + nLineSpacing;
|
|
}
|
|
|
|
// draw the marine name
|
|
if ( asw_marine_names.GetBool() )
|
|
{
|
|
Assert( nMarineNameWidth > 0 );
|
|
{
|
|
int nTextPosX = nBoxCenterX - ( nMarineNameWidth / 2 ) ; // center it on the x
|
|
int nNameLength = Q_wcslen( wszMarineName );
|
|
|
|
// drop shadow
|
|
vgui::surface()->DrawSetTextFont( nMarineFont );
|
|
vgui::surface()->DrawSetTextColor( 0, 0, 0, 200 );
|
|
vgui::surface()->DrawSetTextPos( nTextPosX+1, nCursorY+1 );
|
|
vgui::surface()->DrawPrintText( wszMarineName, nNameLength );
|
|
|
|
// actual text
|
|
vgui::surface()->DrawSetTextColor( nMarineTextColor.r(), nMarineTextColor.g(), nMarineTextColor.b(), 200 );
|
|
vgui::surface()->DrawSetTextPos( nTextPosX, nCursorY );
|
|
vgui::surface()->DrawPrintText( wszMarineName, nNameLength );
|
|
|
|
// advance cursor
|
|
nCursorY += nMarineNameHeight + MAX( nLineSpacing, YRES(2) );
|
|
}
|
|
if ( pwszMarineProfileName && bMarineOnScreen )
|
|
{
|
|
int nTextPosX = nBoxCenterX - ( nMarineProfileNameWidth / 2 ) ; // center it on the x
|
|
int nNameLength = Q_wcslen( pwszMarineProfileName );
|
|
|
|
// drop shadow
|
|
vgui::surface()->DrawSetTextFont( m_hSmallMarineNameFont );
|
|
vgui::surface()->DrawSetTextColor( 0, 0, 0, 200 );
|
|
vgui::surface()->DrawSetTextPos( nTextPosX+1, nCursorY+1 );
|
|
vgui::surface()->DrawPrintText( pwszMarineProfileName, nNameLength );
|
|
|
|
// actual text
|
|
vgui::surface()->DrawSetTextColor( nMarineTextColor.r(), nMarineTextColor.g(), nMarineTextColor.b(), 200 );
|
|
vgui::surface()->DrawSetTextPos( nTextPosX, nCursorY );
|
|
vgui::surface()->DrawPrintText( pwszMarineProfileName, nNameLength );
|
|
|
|
// advance cursor
|
|
nCursorY += nMarineProfileNameHeight + MAX( nLineSpacing, YRES(2) );
|
|
}
|
|
}
|
|
|
|
// draw the talk icon to the left of the name
|
|
if ( !asw_voice_side_icon.GetBool() )
|
|
{
|
|
int nNameWidth = nMarineNameWidth;
|
|
int nNameHeight = nMarineNameHeight;
|
|
PaintTalkingIcon( pMarine, nBoxCenterX - (nNameWidth/2) - (GetTalkingIconSize() + YRES(2)), nCursorY -nNameHeight - (GetTalkingIconSize()-nNameHeight) );
|
|
}
|
|
|
|
// draw the health bar
|
|
if ( nHealthBarHeight > 0 )
|
|
{
|
|
if ( GetClassIconSize( bMarineOnScreen ) <= 0 )
|
|
nCursorY += YRES(2);
|
|
|
|
PaintHealthBar( pMarine, nBoxCenterX, nCursorY, bMarineOnScreen );
|
|
nCursorY += nHealthBarHeight + nLineSpacing;
|
|
}
|
|
|
|
C_ASW_Weapon *pWeapon = pMarine->GetActiveASWWeapon();
|
|
if ( !pWeapon )
|
|
return;
|
|
|
|
// draw the reload bar
|
|
if ( bLocal && pWeapon && pWeapon->IsReloading() && asw_fast_reload_enabled.GetBool() && asw_fast_reload_under_marine.GetBool() )
|
|
{
|
|
PaintReloadBar( pWeapon, nBoxCenterX, nCursorY );
|
|
nCursorY += nHealthBarHeight + nLineSpacing;
|
|
}
|
|
|
|
// draw the using bar
|
|
if ( nUsingBarHeight > 0 )
|
|
{
|
|
PaintUsingBar( pMarine, nBoxCenterX, nCursorY );
|
|
nCursorY += nUsingBarHeight + nLineSpacing;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//AssertMsg1( false, "debugoverlay->ScreenPosition(MarinePos-Vec(0,10,0),screenPos) returned %d", debugoverlay->ScreenPosition( MarinePos - Vector(0,10,0), screenPos ) );
|
|
}
|
|
}
|
|
|
|
#define PORTRAIT_SIZE (80.0f * ( ScreenHeight() / 576.0f ) * 0.6f)
|
|
|
|
float CASWHud3DMarineNames::GetHealthBarMaxWidth( bool bKnockedOut ) const
|
|
{
|
|
if ( bKnockedOut )
|
|
{
|
|
return PORTRAIT_SIZE * 1.5f;
|
|
}
|
|
return PORTRAIT_SIZE;
|
|
}
|
|
float CASWHud3DMarineNames::GetHealthBarMaxHeight( bool bKnockedOut ) const
|
|
{
|
|
if ( bKnockedOut )
|
|
{
|
|
return 12.0f * ( ScreenHeight() / 576.0f ) * 0.6f;
|
|
}
|
|
return 8.0f * ( ScreenHeight() / 576.0f ) * 0.6f;
|
|
}
|
|
|
|
float CASWHud3DMarineNames::GetClassIconSize( bool bOnScreen )
|
|
{
|
|
if ( bOnScreen )
|
|
return 0;
|
|
|
|
//return YRES( 14 );
|
|
return (GetHealthBarMaxHeight( false ) * 2.5);
|
|
}
|
|
|
|
float CASWHud3DMarineNames::GetTalkingIconSize()
|
|
{
|
|
return YRES( 14 );
|
|
//return (GetHealthBarMaxHeight( false ) * 2.5);
|
|
}
|
|
|
|
bool CASWHud3DMarineNames::PaintHealthBar( C_ASW_Marine *pMarine, float xPos, float yPos, bool bOnScreen )
|
|
{
|
|
if ( !pMarine || !pMarine->GetMarineResource() )
|
|
return false;
|
|
|
|
// check if the med satchel is out and if we are highlighting another marine
|
|
|
|
int portrait_size = GetHealthBarMaxWidth( pMarine->m_bKnockedOut );
|
|
int class_icon_size = GetClassIconSize( bOnScreen );
|
|
int bar_height = GetHealthBarMaxHeight( pMarine->m_bKnockedOut );
|
|
|
|
int buffer = YRES( 2 );
|
|
int overall_width = portrait_size + buffer + class_icon_size;
|
|
xPos = xPos - ( ( overall_width ) * 0.5f );
|
|
|
|
// paint class icon next to health bar
|
|
int nClassIcon = -1;
|
|
switch( pMarine->GetMarineProfile()->GetMarineClass() )
|
|
{
|
|
case MARINE_CLASS_NCO: nClassIcon = m_nOfficerClassIcon; break;
|
|
case MARINE_CLASS_SPECIAL_WEAPONS: nClassIcon = m_nSWClassIcon; break;
|
|
case MARINE_CLASS_MEDIC: nClassIcon = m_nMedicClassIcon; break;
|
|
case MARINE_CLASS_TECH: nClassIcon = m_nTechClassIcon; break;
|
|
}
|
|
if ( nClassIcon != -1 && asw_world_healthbar_class_icon.GetBool() )
|
|
{
|
|
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
|
|
vgui::surface()->DrawSetTexture( nClassIcon );
|
|
vgui::surface()->DrawTexturedRect( xPos, yPos, xPos + class_icon_size, yPos + class_icon_size );
|
|
}
|
|
else
|
|
{
|
|
class_icon_size = 0;
|
|
}
|
|
|
|
xPos += class_icon_size + buffer;
|
|
|
|
// if we have the medsatchel out, draw the healthbar bigger
|
|
if ( pMarine->IsInfested() )
|
|
{
|
|
bar_height *= 1.75f;
|
|
yPos += bar_height - (bar_height / 1.75f);
|
|
}
|
|
|
|
yPos += ( class_icon_size - bar_height ) * 0.5f;
|
|
|
|
int portrait_x = xPos;
|
|
|
|
// draw health bar
|
|
int bar_y = yPos;
|
|
int bar_y2 = bar_y + bar_height;
|
|
float fHealth = pMarine->GetMarineResource()->GetHealthPercent();
|
|
if (pMarine->GetMarineResource()->m_bHealthHalved) // if he was wounded from the last mission, halve the size of his health bar
|
|
{
|
|
fHealth *= 0.5f;
|
|
}
|
|
|
|
//if ( pMarine->m_bKnockedOut || pMarine->IsInfested() )
|
|
//{
|
|
// float flDevourTotalTime = pMarine->GetDevourEndTime() - pMarine->GetDevourStartTime();
|
|
// float flDevourCurrentTime = gpGlobals->curtime - pMarine->GetDevourStartTime();
|
|
// fHealth = 1.0f - clamp( flDevourCurrentTime / flDevourTotalTime, 0.0f, 1.0f );
|
|
//}
|
|
|
|
int health_pixels = (portrait_size * fHealth);
|
|
|
|
if (fHealth > 0 && health_pixels <= 0)
|
|
health_pixels = 1;
|
|
int bar_x2 = portrait_x + health_pixels;
|
|
|
|
// white background
|
|
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 128 ) );
|
|
vgui::surface()->DrawFilledRect( portrait_x - 1, bar_y - 1, portrait_x + portrait_size + 1, bar_y2 + 1 );
|
|
|
|
// if he's wounded, draw a grey part
|
|
if ( pMarine->GetMarineResource()->m_bHealthHalved )
|
|
{
|
|
vgui::surface()->DrawSetTexture(m_nWhiteTexture);
|
|
vgui::surface()->DrawSetColor(Color(128,128,128,255));
|
|
vgui::surface()->DrawTexturedRect(portrait_x + (portrait_size * 0.5f), bar_y, portrait_x + portrait_size, bar_y2);
|
|
}
|
|
|
|
// colored part
|
|
Color rgbaBarBrightColor = Color(0,150,150,255);
|
|
Color rgbaBarDarkColor = Color(0,75,75,255);
|
|
|
|
if ( fHealth < 0.5f )
|
|
{
|
|
rgbaBarBrightColor = Color(200,50,0,255);
|
|
rgbaBarDarkColor = Color(100,25,0,255);
|
|
}
|
|
|
|
if ( pMarine->m_bKnockedOut || pMarine->IsInfested() )
|
|
{
|
|
float flFlash = 0.75f + 0.25f * sin( gpGlobals->curtime * 4.0f );
|
|
rgbaBarBrightColor = Color( 255 * flFlash, 0,0,255 );
|
|
rgbaBarDarkColor = Color( 64 * flFlash, 0,0,255 );
|
|
}
|
|
|
|
vgui::surface()->DrawSetColor(rgbaBarBrightColor);
|
|
vgui::surface()->DrawSetTexture(m_nHorizHealthBar);
|
|
vgui::Vertex_t hPoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(portrait_x, bar_y), Vector2D(0,0) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y), Vector2D(fHealth,0) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y2), Vector2D(fHealth,1) ),
|
|
vgui::Vertex_t( Vector2D(portrait_x, bar_y2), Vector2D(0,1) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, hPoints );
|
|
|
|
vgui::surface()->DrawSetColor(rgbaBarDarkColor);
|
|
vgui::surface()->DrawSetTexture(m_nHorizHealthBar);
|
|
vgui::Vertex_t hRemainingPoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y), Vector2D(fHealth,0) ),
|
|
vgui::Vertex_t( Vector2D(portrait_x + portrait_size, bar_y), Vector2D(1,0) ),
|
|
vgui::Vertex_t( Vector2D(portrait_x + portrait_size, bar_y2), Vector2D(1,1) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y2), Vector2D(fHealth,1) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, hRemainingPoints );
|
|
|
|
// draw hurt over the top
|
|
if ( m_nWhiteTexture != -1 && pMarine->GetMarineResource()->GetHurtPulse() > 0 )
|
|
{
|
|
rgbaBarBrightColor[3] *= pMarine->GetMarineResource()->GetHurtPulse();
|
|
vgui::surface()->DrawSetColor( rgbaBarBrightColor );
|
|
vgui::surface()->DrawSetTexture( m_nWhiteTexture );
|
|
vgui::surface()->DrawTexturedPolygon( 4, hPoints );
|
|
}
|
|
|
|
// draw a green bit at the end of the health bar if he's infested
|
|
if (pMarine->GetMarineResource()->IsInfested())
|
|
{
|
|
float fInfestPercent = pMarine->GetMarineResource()->GetInfestedPercent();
|
|
if ( fInfestPercent > fHealth )
|
|
{
|
|
fInfestPercent = fHealth;
|
|
}
|
|
|
|
vgui::surface()->DrawSetTexture(m_nWhiteTexture);
|
|
vgui::surface()->DrawSetColor( Color( 190, 225 + 15 * sinf(gpGlobals->curtime * 5.0f ), 20, 255 ) );
|
|
int fOffset = (fHealth - fInfestPercent) * portrait_size;
|
|
vgui::surface()->DrawTexturedRect(portrait_x + fOffset, bar_y, bar_x2, bar_y2);
|
|
vgui::surface()->DrawSetColor(Color(255,255,255,255));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// find if our marine is using something
|
|
float CASWHud3DMarineNames::GetUsingFraction( C_ASW_Marine *pMarine )
|
|
{
|
|
if ( !pMarine || !pMarine->GetMarineResource() )
|
|
return 0;
|
|
|
|
if (!pMarine->m_hUsingEntity.Get())
|
|
{
|
|
if (pMarine->GetMarineResource()->m_hWeldingDoor.Get())
|
|
{
|
|
if (pMarine->GetMarineResource()->IsFiring())
|
|
return pMarine->GetMarineResource()->m_hWeldingDoor->GetSealAmount();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
IASW_Client_Usable_Entity* pUsable = dynamic_cast<IASW_Client_Usable_Entity*>(pMarine->m_hUsingEntity.Get());
|
|
if (!pUsable)
|
|
return 0;
|
|
|
|
ASWUseAction action;
|
|
if (!pUsable->GetUseAction(action, pMarine))
|
|
return 0;
|
|
|
|
return action.fProgress;
|
|
}
|
|
|
|
|
|
float CASWHud3DMarineNames::GetUsingBarMaxWidth() const
|
|
{
|
|
return PORTRAIT_SIZE;
|
|
}
|
|
float CASWHud3DMarineNames::GetUsingBarMaxHeight() const
|
|
{
|
|
return 7.0f * ( ScreenHeight() / 576.0f ) * 0.6f;
|
|
}
|
|
|
|
bool CASWHud3DMarineNames::PaintUsingBar( C_ASW_Marine *pMarine, float xPos, float yPos )
|
|
{
|
|
if ( !pMarine || !pMarine->GetMarineResource() )
|
|
return false;
|
|
|
|
float fScale = ( ScreenHeight() / 576.0f ) * 0.6f;
|
|
int portrait_size = GetUsingBarMaxWidth();
|
|
xPos -= PORTRAIT_SIZE * 0.5f;
|
|
int portrait_x = xPos;
|
|
int portrait_y = yPos;
|
|
|
|
vgui::surface()->DrawSetColor(Color(255,255,255,255));
|
|
// draw black back
|
|
vgui::surface()->DrawSetTexture(m_nBlackBarTexture);
|
|
|
|
// draw health bar
|
|
int bar_y = portrait_y + (2 * fScale);
|
|
int bar_height = GetUsingBarMaxHeight();
|
|
int bar_y2 = bar_y + bar_height;
|
|
float fFraction = GetUsingFraction( pMarine );
|
|
if ( fFraction <= 0 )
|
|
return false;
|
|
int using_pixels = (portrait_size * fFraction);
|
|
|
|
if (fFraction > 0 && using_pixels <= 0)
|
|
using_pixels = 1;
|
|
int bar_x2 = portrait_x + using_pixels;
|
|
int border = YRES(1);
|
|
// black part first
|
|
vgui::surface()->DrawTexturedRect(portrait_x - border, bar_y - border, portrait_x + portrait_size + border * 2 - 1, bar_y2 + border * 2 - 1);
|
|
|
|
// red part
|
|
vgui::surface()->DrawSetTexture(m_nVertAmmoBar);
|
|
vgui::Vertex_t hpoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(portrait_x, bar_y), Vector2D(0,0) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y), Vector2D(fFraction,0) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y2), Vector2D(fFraction,1) ),
|
|
vgui::Vertex_t( Vector2D(portrait_x, bar_y2), Vector2D(0,1) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, hpoints );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CASWHud3DMarineNames::PaintReloadBar( C_ASW_Weapon *pWeapon, float xPos, float yPos )
|
|
{
|
|
if ( !pWeapon )
|
|
return false;
|
|
|
|
bool bFailure = pWeapon->m_bFastReloadFailure;
|
|
bool bSuccess = pWeapon->m_bFastReloadSuccess;
|
|
|
|
float flBGAlpha = 255.0f;
|
|
Color colorBG = Color( 32, 32, 32, flBGAlpha );
|
|
Color colorWindow = Color( 170, 170, 170, 255 );
|
|
Color colorBar = Color( 255, 255, 255, 128 );
|
|
float flAlphaFade = 1.0f;
|
|
|
|
int class_icon_size = GetClassIconSize( true );
|
|
int t = GetHealthBarMaxHeight( false );
|
|
int w = GetHealthBarMaxWidth( false );
|
|
|
|
int iGap = YRES( 2 );
|
|
int overall_width = w + iGap + class_icon_size;
|
|
|
|
xPos += class_icon_size + iGap;
|
|
yPos += ( class_icon_size - t ) * 0.5f;
|
|
|
|
int iYPos = yPos;
|
|
xPos = xPos - ( ( overall_width ) * 0.5f );
|
|
int iXPos = xPos;
|
|
|
|
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;
|
|
|
|
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, 128 * 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, 128 * flAlphaFade );
|
|
}
|
|
|
|
// white border
|
|
vgui::surface()->DrawSetColor( colorBar );
|
|
vgui::surface()->DrawFilledRect( iXPos - 1, iYPos - 1, iXPos + w + 1, iYPos+t + 1 );
|
|
|
|
// draw the BG first
|
|
vgui::surface()->DrawSetColor(colorBG);
|
|
vgui::surface()->DrawSetTexture(m_nFastReloadBarBG);
|
|
vgui::Vertex_t bgpoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(iXPos, iYPos), Vector2D(0, 0) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w, iYPos), Vector2D(1, 0) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w, iYPos+t), Vector2D(1, 1) ),
|
|
vgui::Vertex_t( Vector2D(iXPos, iYPos+t), Vector2D(0, 1) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, bgpoints );
|
|
|
|
// then the charging bar
|
|
vgui::surface()->DrawSetColor(colorWindow);
|
|
vgui::surface()->DrawSetTexture(m_nHorizHealthBar);
|
|
vgui::Vertex_t chargepoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(iXPos+w*m_flLastFastReloadStart, iYPos+1), Vector2D(m_flLastFastReloadStart, 0) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w*m_flLastFastReloadEnd, iYPos+1), Vector2D(m_flLastFastReloadEnd, 0) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w*m_flLastFastReloadEnd, iYPos+t-1), Vector2D(m_flLastFastReloadEnd, 1) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w*m_flLastFastReloadStart, iYPos+t-1), Vector2D(m_flLastFastReloadStart, 1) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, chargepoints );
|
|
|
|
// now the delay bar
|
|
vgui::surface()->DrawSetColor(colorBar);
|
|
vgui::surface()->DrawSetTexture(m_nWhiteTexture);
|
|
vgui::Vertex_t delaypoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(iXPos+w*(MAX(m_flLastReloadProgress-0.01f,0)), iYPos), Vector2D( MAX(m_flLastReloadProgress-0.02f,0), 0 ) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w*(MAX(m_flLastReloadProgress+0.01f,0)), iYPos), Vector2D( m_flLastReloadProgress, 0) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w*(MAX(m_flLastReloadProgress+0.01f,0)), iYPos+t), Vector2D( m_flLastReloadProgress, 0) ),
|
|
vgui::Vertex_t( Vector2D(iXPos+w*(MAX(m_flLastReloadProgress-0.01f,0)), iYPos+t), Vector2D( MAX(m_flLastReloadProgress-0.02f,0), 0 ) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, delaypoints );
|
|
|
|
///////////
|
|
return true;
|
|
}
|
|
|
|
extern void ASW_GetLineCircle(int index, float &alien_x, float &alien_y, float &alien_radius, float &marine_x, float &marine_y, Vector2D &LineDir, int &iCol);
|
|
void CASWHud3DMarineNames::PaintAimingDebug()
|
|
{
|
|
vgui::surface()->DrawSetColor(Color(255,255,255,192));
|
|
for ( int i = 0; i < 25; i++ )
|
|
{
|
|
float alien_x, alien_y, alien_radius, marine_x, marine_y;
|
|
int col;
|
|
Vector2D Line;
|
|
ASW_GetLineCircle(i, alien_x, alien_y, alien_radius, marine_x, marine_y, Line, col);
|
|
if (alien_radius != 0)
|
|
{
|
|
if (col == 0)
|
|
g_pMatSystemSurface->DrawColoredCircle(alien_x, alien_y, alien_radius, 255, 0, 0, 255);
|
|
else
|
|
g_pMatSystemSurface->DrawColoredCircle(alien_x, alien_y, alien_radius, 255, 255, 255, 255);
|
|
//g_pMatSystemSurface->DrawColoredCircle(marine_x, marine_y, alien_radius, 255, 0, 0, 255);
|
|
vgui::surface()->DrawLine(marine_x, marine_y, marine_x + Line.x * 100, marine_y + Line.y * 100);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CASWHud3DMarineNames::UpdateHealthTooltip()
|
|
{
|
|
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
|
if (pPlayer)
|
|
{
|
|
if (pPlayer->GetMarine() && dynamic_cast<C_ASW_Weapon_Medical_Satchel*>(pPlayer->GetMarine()->GetActiveASWWeapon()))
|
|
{
|
|
C_ASW_Marine* pHealMarine = dynamic_cast<C_ASW_Marine*>( ASWInput()->GetHighlightEntity() );
|
|
SetHealthMarine(pHealMarine);
|
|
}
|
|
else
|
|
{
|
|
SetHealthMarine(NULL);
|
|
}
|
|
}
|
|
// fade in/out as the marine changes
|
|
if ( m_bHealthQueuedMarine )
|
|
{
|
|
// if we have a marine queued up, we better fade out
|
|
m_fHealthAlpha -= gpGlobals->frametime * 5;
|
|
|
|
if ( m_fHealthAlpha <= 0 )
|
|
{
|
|
// finished fading out, set our new marine and clear the queued
|
|
if ( m_hHealthMarine != m_hHealthQueuedMarine )
|
|
{
|
|
m_hHealthMarine = m_hHealthQueuedMarine;
|
|
|
|
// Fire event
|
|
if ( m_hHealthMarine.Get() )
|
|
{
|
|
IGameEvent * event = gameeventmanager->CreateEvent( "player_heal_target" );
|
|
if ( event )
|
|
{
|
|
event->SetInt( "userid", pPlayer->GetUserID() );
|
|
event->SetInt( "entindex", m_hHealthMarine.Get()->entindex() );
|
|
gameeventmanager->FireEventClientSide( event );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IGameEvent * event = gameeventmanager->CreateEvent( "player_heal_target_none" );
|
|
if ( event )
|
|
{
|
|
event->SetInt( "userid", pPlayer->GetUserID() );
|
|
gameeventmanager->FireEventClientSide( event );
|
|
}
|
|
}
|
|
}
|
|
m_hHealthQueuedMarine = NULL;
|
|
m_bHealthQueuedMarine = false;
|
|
m_fHealthAlpha = 0;
|
|
}
|
|
}
|
|
else if (m_hHealthMarine.Get())
|
|
{
|
|
// no queue and a valid current, make sure it's shown
|
|
m_fHealthAlpha += gpGlobals->frametime * 5;
|
|
if (m_fHealthAlpha > 1.0f)
|
|
m_fHealthAlpha = 1.0f;
|
|
}
|
|
|
|
|
|
// check for updating health
|
|
C_ASW_Marine* pMarine = m_hHealthMarine.Get();
|
|
|
|
// hide the panel if we have no marine to report on
|
|
if (!pMarine && m_fHealthAlpha > 0)
|
|
{
|
|
if (!m_bHealthQueuedMarine)
|
|
{
|
|
m_hHealthQueuedMarine = NULL;
|
|
m_bHealthQueuedMarine = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CASWHud3DMarineNames::SetHealthMarine(C_ASW_Marine *pMarine)
|
|
{
|
|
if (m_hHealthMarine.Get() != pMarine && !(m_bHealthQueuedMarine && pMarine == m_hHealthQueuedMarine.Get()))
|
|
{
|
|
m_hHealthQueuedMarine = pMarine;
|
|
m_bHealthQueuedMarine = true;
|
|
}
|
|
}
|
|
|
|
static const char* s_FontTestNames[]={
|
|
"Sansman8",
|
|
"Sansman9",
|
|
"Sansman10",
|
|
"Sansman11",
|
|
"Sansman12",
|
|
"Sansman13",
|
|
"Sansman14",
|
|
"Sansman16",
|
|
"Sansman17",
|
|
"Sansman18",
|
|
"Sansman19",
|
|
"Sansman20"
|
|
};
|
|
|
|
void CASWHud3DMarineNames::PaintFontTest()
|
|
{
|
|
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
|
|
if (!pScheme)
|
|
return;
|
|
|
|
int num_fonts = NELEMS(s_FontTestNames);
|
|
int y = ScreenHeight() * 0.1f;
|
|
int x = ScreenHeight() * 0.3f;
|
|
for (int i=0;i<num_fonts;i++)
|
|
{
|
|
vgui::HFont hFont = pScheme->GetFont(s_FontTestNames[i], false);
|
|
g_pMatSystemSurface->DrawColoredText(hFont, x, y, 255, 255,
|
|
255, 255, "%s Bastille", s_FontTestNames[i]);
|
|
y += vgui::surface()->GetFontTall(hFont);
|
|
}
|
|
|
|
vgui::HFont hFont = pScheme->GetFont( "Default", IsProportional() );
|
|
g_pMatSystemSurface->DrawColoredText(hFont, x, y, 255, 255,
|
|
255, 255, "Default Bastille");
|
|
y += vgui::surface()->GetFontTall(hFont);
|
|
}
|
|
|
|
void CASWHud3DMarineNames::PaintTalkingIcon( C_ASW_Marine *pMarine, float xPos, float yPos )
|
|
{
|
|
if ( !pMarine || !ASWGameResource() || ASWGameResource()->IsOfflineGame() )
|
|
return;
|
|
|
|
C_ASW_Player* pPlayer = pMarine->GetCommander();
|
|
if ( !pPlayer )
|
|
return;
|
|
|
|
C_ASW_Player *local = C_ASW_Player::GetLocalASWPlayer();
|
|
if (!local)
|
|
return;
|
|
|
|
CVoiceStatus *pVoiceMgr = GetClientVoiceMgr();
|
|
int index = pPlayer->entindex();
|
|
|
|
bool bTalking = false;
|
|
|
|
if ( pPlayer == local )
|
|
{
|
|
bTalking = pVoiceMgr->IsLocalPlayerSpeakingAboveThreshold( FirstValidSplitScreenSlot() );
|
|
}
|
|
else
|
|
{
|
|
bTalking = pVoiceMgr->IsPlayerSpeaking( index );
|
|
}
|
|
|
|
float flColorSinR = 0;
|
|
float flColorSinG = 0;
|
|
float flColorSinB = 0;
|
|
float flAlpha = 255;
|
|
|
|
if ( pPlayer == local && bTalking )
|
|
{
|
|
flColorSinR = 234+(sin( gpGlobals->curtime * 8) + 1) * 10;
|
|
flColorSinG = flColorSinR;
|
|
flColorSinB = 130+(sin( gpGlobals->curtime * 8) + 1) * 60;
|
|
}
|
|
else if ( bTalking )
|
|
{
|
|
flColorSinR = 170+(sin( gpGlobals->curtime * 8) + 1) * 30;
|
|
flColorSinG = flColorSinR;
|
|
flColorSinB = 210+(sin( gpGlobals->curtime * 8) + 1) * 20;
|
|
}
|
|
|
|
if ( m_3DSpeakingList.IsBitSet( index ) || bTalking )
|
|
{
|
|
if ( bTalking )
|
|
{
|
|
m_3DSpeakingList.Set( index, true );
|
|
m_flLastTalkingTime[index-1] = gpGlobals->curtime;
|
|
}
|
|
else
|
|
{
|
|
flColorSinR = 230;
|
|
flColorSinG = 230;
|
|
flColorSinB = 230;
|
|
flAlpha *= clamp( ((m_flLastTalkingTime[index-1]+1.5f) - gpGlobals->curtime)/1.5f, 0.0f, 1.0f );
|
|
}
|
|
|
|
if ( flAlpha <= 0 )
|
|
{
|
|
m_3DSpeakingList.Set( index, false );
|
|
}
|
|
|
|
if ( pMarine->IsInhabited() )
|
|
{
|
|
int iSize = GetTalkingIconSize();
|
|
vgui::surface()->DrawSetColor( flColorSinR, flColorSinG, flColorSinB, flAlpha );
|
|
vgui::surface()->DrawSetTexture( m_nTalkingIcon );
|
|
vgui::surface()->DrawTexturedRect( xPos, yPos, xPos + iSize, yPos + iSize );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CASWHud3DMarineNames::PaintTrackedHealth()
|
|
{
|
|
for ( int i = 0; i < IHealthTracked::AutoList().Count(); i++ )
|
|
{
|
|
IHealthTracked *pTracked = static_cast< IHealthTracked* >( IHealthTracked::AutoList()[ i ] );
|
|
if ( !pTracked )
|
|
continue;
|
|
|
|
pTracked->PaintHealthBar( this );
|
|
}
|
|
}
|
|
|
|
|
|
bool CASWHud3DMarineNames::PaintGenericBar( Vector vWorldPos, float flProgress, Color rgbaBarColor, float flSizeMultiplier, const Vector2D &offset )
|
|
{
|
|
Vector screenPos;
|
|
|
|
const int nMaxX = ScreenWidth() - 150;
|
|
const int nMaxY = ScreenHeight() - 100;
|
|
debugoverlay->ScreenPosition( vWorldPos - Vector(0,10,0), screenPos );
|
|
if ( screenPos.x < 0 || screenPos.x > nMaxX || screenPos.y < 0 || screenPos.y > nMaxY )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
screenPos.x += offset.x;
|
|
screenPos.y += offset.y;
|
|
|
|
float fScale = ( ScreenHeight() / 576.0f ) * 0.6f;
|
|
int portrait_size = GetUsingBarMaxWidth() * flSizeMultiplier;
|
|
screenPos.x -= PORTRAIT_SIZE * 0.5f;
|
|
int portrait_x = screenPos.x;
|
|
int portrait_y = screenPos.y;
|
|
|
|
// draw health bar
|
|
int bar_y = portrait_y + (2 * fScale);
|
|
int bar_height = GetUsingBarMaxHeight() * flSizeMultiplier;
|
|
int bar_y2 = bar_y + bar_height;
|
|
if ( flProgress <= 0 )
|
|
return false;
|
|
int using_pixels = (portrait_size * flProgress);
|
|
|
|
if ( flProgress > 0 && using_pixels <= 0 )
|
|
using_pixels = 1;
|
|
int bar_x2 = portrait_x + using_pixels;
|
|
int border = YRES(1);
|
|
|
|
// black part first
|
|
vgui::surface()->DrawSetColor( Color( 255, 255, 255, rgbaBarColor.a() ) );
|
|
vgui::surface()->DrawSetTexture( m_nBlackBarTexture );
|
|
vgui::surface()->DrawTexturedRect( portrait_x - border, bar_y - border, portrait_x + portrait_size + border * 2, bar_y2 + border * 2 );
|
|
|
|
// red part
|
|
vgui::surface()->DrawSetColor( rgbaBarColor );
|
|
vgui::surface()->DrawSetTexture( m_nVertAmmoBar );
|
|
vgui::Vertex_t hpoints[4] =
|
|
{
|
|
vgui::Vertex_t( Vector2D(portrait_x, bar_y), Vector2D(0,0) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y), Vector2D(flProgress,0) ),
|
|
vgui::Vertex_t( Vector2D(bar_x2, bar_y2), Vector2D(flProgress,1) ),
|
|
vgui::Vertex_t( Vector2D(portrait_x, bar_y2), Vector2D(0,1) )
|
|
};
|
|
vgui::surface()->DrawTexturedPolygon( 4, hpoints );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CASWHud3DMarineNames::PaintGenericText( Vector vWorldPos, char *pText, Color vTextColor, float flSizeMultiplier, const Vector2D &offset )
|
|
{
|
|
Vector screenPos;
|
|
|
|
const int nMaxX = ScreenWidth() - 150;
|
|
const int nMaxY = ScreenHeight() - 100;
|
|
debugoverlay->ScreenPosition( vWorldPos - Vector(0,10,0), screenPos );
|
|
if ( screenPos.x < 0 || screenPos.x > nMaxX || screenPos.y < 0 || screenPos.y > nMaxY )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// work around error in design of IMatSystemSurface
|
|
int nTextWidth = g_pMatSystemSurface->DrawTextLen( m_hPlayerNameFont, pText );
|
|
int nTextHeight = vgui::surface()->GetFontTall(m_hPlayerNameFont);
|
|
|
|
screenPos.x += offset.x;
|
|
screenPos.y += offset.y * nTextHeight;
|
|
|
|
// g_pMatSystemSurface->GetTextSize( nMarineFont, UNICODE VERSION OF pText, nMarineNameWidth, nMarineNameHeight );
|
|
|
|
int nTextPosX = screenPos.x - (nTextWidth/2) ; // centre it on the x,y
|
|
int nTextPosY = screenPos.y - (nTextHeight/2);
|
|
|
|
//drop shadow
|
|
g_pMatSystemSurface->DrawColoredText(m_hPlayerNameFont, nTextPosX+1, nTextPosY+1,
|
|
0, 0, 0, 200,
|
|
pText );
|
|
// actual text
|
|
g_pMatSystemSurface->DrawColoredText(m_hPlayerNameFont, nTextPosX, nTextPosY,
|
|
vTextColor.r(), vTextColor.g(), vTextColor.b(), 200,
|
|
pText );
|
|
|
|
return true;
|
|
} |